题意:
给出你序列 a,在序列 a 上执行两种操作;
① 0 :查询有多少连续的片段[L,...,R],满足 a[L,...,R] > l;
② 1 p d :将第 p 个数增加 d;
思路:
1 int n,m,l; 2 ll a[maxn]; 3 int fa[maxn];///a[L,...,x] > l 的最小的L; 4 /** 5 _bit[0][x]:a[x] > l,_bit[0][x]=1,反之为0; 6 _bit[1][x]:a[L,...,R] > l,_bit[L]=1,_bit[L+1,...,R]=0, 7 即满足条件的连续片段[L,...R],只将开始位置L赋为1 8 */ 9 bitset<maxn>_bit[2];
在 m 次操作中,只有出现 a[p] ≤ l && a[p]+d > l 时,才有可能合并区间;
即a[L,...,p-1] > l , a[p+1,...,R] > l ,现在 a[p]+d > l 使得 [L,...,p-1] 与 [p+1,...,R] 可以合并成 a[L,...R] > l;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn=1e5+50; 5 6 int n,m,l; 7 ll a[maxn]; 8 int fa[maxn];///a[L,...,x] > l 的最小的L; 9 /** 10 _bit[0][x]:a[x] > l,_bit[0][x]=1,反之为0; 11 _bit[1][x]:a[L,...,R] > l,_bit[L]=1,_bit[L+1,...,R]=0, 12 即满足条件的连续片段[L,...R],只将开始位置L赋为1 13 */ 14 bitset<maxn>_bit[2]; 15 16 int Find(int x) 17 { 18 return x == fa[x] ? x:fa[x]=Find(fa[x]); 19 } 20 void Solve() 21 { 22 for(int i=1;i <= n;++i) 23 { 24 if(a[i] <= l) 25 continue; 26 27 _bit[0].set(i); 28 29 int x=i; 30 if(_bit[0][i-1]) 31 x=Find(i-1); 32 fa[i]=x; 33 _bit[1].set(x); 34 } 35 for(int i=1;i <= m;++i) 36 { 37 int que; 38 scanf("%d",&que); 39 if(!que) 40 printf("%d\n",_bit[1].count()); 41 else 42 { 43 int p,d; 44 scanf("%d%d",&p,&d); 45 if(_bit[0][p]) 46 continue; 47 48 a[p] += d; 49 if(a[p] <= l) 50 continue; 51 52 _bit[0].set(p); 53 54 int x=p; 55 if(_bit[0][p-1]) 56 x=Find(p-1);///查找a[L,...,p]>l的最小的L; 57 fa[p]=x; 58 ///[L,...,R] 59 ///查找最大的R 60 for(int j=p+1;_bit[0][j];++j)///每个数顶多遍历两边 61 { 62 fa[j]=x;///合并[L,...,R]到x上 63 _bit[1][j]=0; 64 } 65 _bit[1].set(x); 66 } 67 } 68 } 69 int main() 70 { 71 scanf("%d%d%d",&n,&m,&l); 72 for(int i=1;i <= n;++i) 73 { 74 fa[i]=i; 75 scanf("%lld",a+i); 76 } 77 Solve(); 78 79 return 0; 80 }