CF1117G Recursive Queries
题意:给定一个序列,定义[l, r]的最大值在m处,求f(l, r) = f(l, m - 1) + (r - l + 1) + f(m + 1, r)。多次询问。100w。
解:考虑这个区间内每个数作为最大值的时候,它的(r - l + 1)的贡献。
显然就是min(r, rci - 1) - max(l, lci + 1) + 1
我们分别计算这两部分。
min(r, rci - 1)这个东西,发现当一个i的rci - 1比r小的时候,就会是一个定值。否则就是r。而我们要区间求和,于是开一个线段树。把询问挂在区间上从右往左扫,线段树每个位置维护rci - 1是否比当前的r小。如果比当前r大了,就改掉。
第二项同理。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 5 const int N = 1000010; 6 7 struct Node { 8 int l, r, id; 9 }node[N]; 10 11 int val[N], n, q, lc[N], rc[N], stk[N], top; 12 LL ans[N]; 13 14 std::vector<int> v[N], v2[N]; 15 16 LL sum[N << 2], sum2[N << 2]; 17 18 inline void pushup(int o) { 19 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 20 sum2[o] = sum2[o << 1] + sum2[o << 1 | 1]; 21 return; 22 } 23 24 void build(int f, int l, int r, int o) { 25 if(l == r) { 26 if(f == 1) { 27 sum[o] = lc[r] + 1; 28 } 29 else { 30 sum[o] = rc[r] - 1; 31 } 32 sum2[o] = 0; 33 return; 34 } 35 int mid = (l + r) >> 1; 36 build(f, l, mid, o << 1); 37 build(f, mid + 1, r, o << 1 | 1); 38 pushup(o); 39 return; 40 } 41 42 LL ask(int L, int R, int v, int l, int r, int o) { 43 if(L <= l && r <= R) { 44 return sum[o] + v * sum2[o]; 45 } 46 int mid = (l + r) >> 1; 47 LL ans = 0; 48 if(L <= mid) ans = ask(L, R, v, l, mid, o << 1); 49 if(mid < R) ans += ask(L, R, v, mid + 1, r, o << 1 | 1); 50 return ans; 51 } 52 53 void change(int p, int l, int r, int o) { 54 if(l == r) { 55 sum[o] = 0; 56 sum2[o] = 1; 57 return; 58 } 59 int mid = (l + r) >> 1; 60 if(p <= mid) change(p, l, mid, o << 1); 61 else change(p, mid + 1, r, o << 1 | 1); 62 pushup(o); 63 return; 64 } 65 66 int main() { 67 68 scanf("%d%d", &n, &q); 69 for(int i = 1; i <= n; i++) { 70 scanf("%d", &val[i]); 71 } 72 73 for(int i = 1; i <= q; i++) { 74 scanf("%d", &node[i].l); 75 node[i].id = i; 76 } 77 for(int i = 1; i <= q; i++) { 78 scanf("%d", &node[i].r); 79 } 80 81 for(int i = 1; i <= n; i++) { 82 while(top && val[stk[top]] <= val[i]) { 83 rc[stk[top]] = i; 84 top--; 85 } 86 lc[i] = stk[top]; 87 stk[++top] = i; 88 } 89 while(top) { 90 rc[stk[top]] = n + 1; 91 top--; 92 } 93 94 /// solve L 95 for(int i = 1; i <= n; i++) { 96 v[lc[i]].push_back(i); 97 } 98 for(int i = 1; i <= q; i++) { 99 v2[node[i].l].push_back(i); 100 } 101 102 103 build(1, 1, n, 1); 104 for(int i = 1; i <= n; i++) { 105 for(int j = 0; j < (int)v[i - 1].size(); j++) { 106 /// v[i - 1][j] 107 change(v[i - 1][j], 1, n, 1); 108 } 109 for(int j = 0; j < (int)v2[i].size(); j++) { 110 int x = v2[i][j]; 111 ans[x] = -ask(node[x].l, node[x].r, i, 1, n, 1); 112 } 113 } 114 115 /// solve R 116 for(int i = 0; i <= n; i++) { 117 v[i].clear(); 118 v2[i].clear(); 119 } 120 for(int i = 1; i <= n; i++) { 121 v[rc[i]].push_back(i); 122 } 123 for(int i = 1; i <= q; i++) { 124 v2[node[i].r].push_back(i); 125 } 126 build(2, 1, n, 1); 127 for(int i = n; i >= 1; i--) { 128 for(int j = 0; j < (int)v[i + 1].size(); j++) { 129 /// v[i + 1][j] 130 change(v[i + 1][j], 1, n, 1); 131 } 132 for(int j = 0; j < (int)v2[i].size(); j++) { 133 int x = v2[i][j]; 134 ans[x] += ask(node[x].l, node[x].r, i, 1, n, 1); 135 } 136 } 137 138 for(int i = 1; i <= q; i++) { 139 printf("%lld ", ans[i] + node[i].r - node[i].l + 1); 140 } 141 142 return 0; 143 }