Mail.Ru Cup 2018 Round 2 B. Alice and Hairdresser (bitset<> or 其他)
题意:
给出你序列 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 }
ac后看了一下standings,看到了 tourist ,然后,偷偷%了一眼大神的代码;
啊,简洁+高效,tql;
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 9 void Solve() 10 { 11 int ans=0; 12 for(int i=1;i <= n;++i) 13 if(a[i] > l && a[i-1] <= l)///[L,..,R]只在L处使得ans+1 14 ans++; 15 16 for(int i=1;i <= m;++i) 17 { 18 int que; 19 scanf("%d",&que); 20 if(!que) 21 printf("%d\n",ans); 22 else 23 { 24 int p,d; 25 scanf("%d%d",&p,&d); 26 if(a[p] > l) 27 continue; 28 a[p] += d; 29 30 ///[L,..,R]只在L处使得ans+1 31 if(a[p] > l && a[p-1] <= l) 32 ans++; 33 34 ///如果p使得[L,...,p-1]与[p+1,...,R]合并 35 ///[L,...,p-1]使得ans+1,[p+1,...,R]使得ans+1 36 ///所以ans需-1 37 if(a[p] > l && a[p+1] > l) 38 ans--; 39 } 40 } 41 } 42 int main() 43 { 44 scanf("%d%d%d",&n,&m,&l); 45 for(int i=1;i <= n;++i) 46 scanf("%lld",a+i); 47 Solve(); 48 49 return 0; 50 }