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 }
View Code

 

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 }
View Code

 

posted @ 2019-05-24 10:04  HHHyacinth  阅读(204)  评论(0编辑  收藏  举报