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 }
AC代码

 

posted @ 2019-05-01 15:58  huyufeifei  阅读(355)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜