zoukankan      html  css  js  c++  java
  • 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
    ",_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
    ",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
  • 相关阅读:
    数学之矩阵快速幂
    数学篇之高斯消元
    P1033自由落体
    P1258小车问题
    P1072Hankson的趣味题
    P2837晚餐队列安排
    P3811 乘法逆元
    P1002过河卒
    P1507 NASA的食物计划
    P1079 Vigenère 密码
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10916367.html
Copyright © 2011-2022 走看看