标签:style blog color os io ar for div 问题
纪念自己过的第一道CF Div.1的E题,不过好多的地方都有点的不太理解,差不多可以说是照着比人的代码打了一遍,以后有空自己再写一遍......
首先,把题目转化为一个贪心问题:对于每个询问(x, y),发现在
这两个条件中,可以想象一下,从y, y走到1, l的某个位置,而且路径上y坐标不会增加,而且l是[l,y]中最小的那个数,代价就为sum[y] - sum[l] + a[l]·(x - y + l)
最小的那个点肯定要尽可能多用
于是一顿乱推得到一个 sum[y] + a[l]·(x - y) + a[l]·l - sum[l], 令k = a[l], X = x - y, b = a[l] * l - sum[l],发现和y = k * x + b很像,于是就可以依靠这个来解决问题了
期中sum[y]在那个式子里面可有可无,所以可以单独提出来
然后就是靠线段树来维护一个凸包,为什么要用凸包呢?为什么要会线段树呢?
如果你求出了一个下凸包(其实感觉有点像半平面交),对于一个点x,凸包上的直线满足一个很好的性质,就是这些线是按k排序的,于是就可以二分
怎么维护呢?类似于归并排序的方法,不过为了方便询问就利用了线段树
代码
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <deque> 5 #include <cmath> 6 #include <vector> 7 #include <string> 8 #include <cstdio> 9 #include <cstdlib> 10 #include <cstring> 11 #include <cassert> 12 #include <iostream> 13 #include <algorithm> 14 15 using namespace std; 16 17 typedef long long LL; 18 typedef pair <int, int> PII; 19 20 const int N = 1e5 + 7; 21 const int INF = 0x3f3f3f3f; 22 const int MOD = 1e9 + 7; 23 const double EPS = 1e-6; 24 const double PI = acos(-1.0); 25 26 int data[N], sum[N]; 27 28 struct ConvexHull{ 29 vector <int> k, b; 30 void clear(){ 31 k.clear(); 32 b.clear(); 33 } 34 double Intersect(int k1, int b1, int k2, int b2){ 35 return (double)(b2 - b1) / (k1 - k2); 36 } 37 void push(int kk, int bb){ 38 int n = k.size(); 39 while (n > 1 && ((k.back() == kk && b.back() > bb) || (k.back() != kk && 40 Intersect(k[n - 1], b[n - 1], k[n - 2], b[n - 2]) > Intersect(k[n - 1], b[n - 1], kk, bb)))){ 41 --n; 42 k.pop_back(); 43 b.pop_back(); 44 } 45 while (n && k.back() == kk && b.back() > bb){ 46 --n; 47 k.pop_back(); 48 b.pop_back(); 49 } 50 if (n && k.back() == kk && b.back() <= bb){ 51 return; 52 } 53 k.push_back(kk); 54 b.push_back(bb); 55 } 56 int get(int x){ 57 // printf("Calc %d\n", x); 58 // int res = INF; 59 // for (int i = 0; i < k.size(); ++i){ 60 // res = min(); 61 // } 62 int l = 0, r = k.size() - 1, mid; 63 while (l < r){ 64 mid = (l + r) >> 1; 65 if (k[mid] * x + b[mid] < k[mid + 1] * x + b[mid + 1]) 66 r = mid; 67 else 68 l = mid + 1; 69 } 70 return k[l] * x + b[l]; 71 } 72 void debug(){ 73 for (int i = 0; i < k.size(); ++i) 74 printf("%d %d\n", k[i], b[i]); 75 } 76 }; 77 78 struct Node{ 79 int a, b; 80 ConvexHull g; 81 Node *l, *r; 82 }; 83 84 struct SegmentTree{ 85 Node tree[N << 1], *root; 86 int pos; 87 88 void merge(ConvexHull &res, const ConvexHull &a, const ConvexHull & b){ 89 res.clear(); 90 int p1 = 0, p2 = 0; 91 while (p1 < a.k.size() && p2 < b.k.size()){ 92 if (a.k[p1] > b.k[p2]){ 93 res.push(a.k[p1], a.b[p1]); 94 ++p1; 95 } else { 96 res.push(b.k[p2], b.b[p2]); 97 ++p2; 98 } 99 } 100 while (p1 < a.k.size()){ 101 res.push(a.k[p1], a.b[p1]); 102 ++p1; 103 } 104 while (p2 < b.k.size()){ 105 res.push(b.k[p2], b.b[p2]); 106 ++p2; 107 } 108 } 109 110 Node *build(int a, int b){ 111 Node *root = &tree[++pos]; 112 root->a = a; 113 root->b = b; 114 if (a == b){ 115 root->g.clear(); 116 root->g.push(data[a], data[a] * a - sum[a]); 117 return root; 118 } 119 int mid = (a + b) >> 1; 120 root->l = build(a, mid); 121 root->r = build(mid + 1, b); 122 // printf("Merge : [%d - %d]\n", a, b); 123 // printf("A : \n"); 124 // root->l->g.debug(); 125 // printf("B : \n"); 126 // root->r->g.debug(); 127 merge(root->g, root->l->g, root->r->g); 128 // printf("Res : \n"); 129 // root->g.debug(); 130 return root; 131 } 132 133 void init(int n){ 134 pos = 0; 135 root = build(1, n); 136 } 137 138 int find(Node *root, int a, int b, int x){ 139 if (a <= root->a && root->b <= b){ 140 return root->g.get(x); 141 } 142 int mid = (root->a + root->b) >> 1, res = 0; 143 if (a <= mid) 144 res = min(res, find(root->l, a, b, x)); 145 if (b > mid) 146 res = min(res, find(root->r, a, b, x)); 147 return res; 148 } 149 150 int query(int x, int y){ 151 return find(root, y - x + 1, y, x - y); 152 } 153 }tree; 154 155 int main(void){ 156 freopen("a.in", "r", stdin) 157 freopen("a.out", "w", stdout); 158 int n; 159 scanf("%d", &n); 160 for (int i = 1; i <= n; ++i){ 161 scanf("%d", &data[i]); 162 sum[i] = sum[i - 1] + data[i]; 163 } 164 tree.init(n); 165 int Q, x, y; 166 scanf("%d", &Q); 167 while (Q--){ 168 scanf("%d%d", &x, &y); 169 printf("%d\n", sum[y] + tree.query(x, y)); 170 } 171 return 0; 172 }
Codeforces Round #260(Div. 1)E
标签:style blog color os io ar for div 问题
原文地址:http://www.cnblogs.com/addf/p/3949921.html