• ------------!


    题目背景

      在做模拟题的时候,打表出规律,结果找错了(打脸)。

    题目描述
    pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 3的倍数。他想研究对于二进制,是否也有类似的性质。 于是他生成了一个长为 n的二进制串,希望你对于这个二进制串的一个子区间,能求出其有多少位置不同的连续子串,满足在重新排列后(可包含前导 0)是一个3的倍数。两个位置不同的子区间指开始位置不同或结束位置不同。 由于他想尝试尽量多的情况,他有时会修改串中的一个位置,并且会进行多次询问。 输入格式
    输入第一行包含一个正整数 n,表示二进制数的长度。
    之后一行 n个空格隔开的整数,保证均是 0或 1,表示该二进制串。
    之后一行一个整数 m,表示询问和修改的总次数。
    之后 m行每行为 1 i,表示 pupil 修改了串的第 i个位置(0变成 1或 1 变成 0),或 2 l r,表示 pupil 询问的子区间是 [l,r]。
    串的下标从 1开始。 输出格式


    对于每次询问,输出一行一个整数表示对应该询问的结果

    样例输入

    4

    1 0 1 0

    3

    2 1 3

    1 3

    2 3 4

    样例输出

    2

    3

    我所理解的题目

      给定一个 01 串,接下来有若干询问与修改。

    询问 :给定一个区间【L,R】,你需要回答在这一个区间中有多少个子区间包含不止一个或者全为 0

    修改 :将一个数取反。

      找到这个规律后,我就----莫队,带修,提分。

      然后,我发现我只会带log的带修。。。。。。

      于是,我又惊奇的发现,可以在线处理!

      答案显然为区间个数减去不合法的区间-------包含且只包含一个 1 的区间个数。

        额,公式打不出来。


      对于询问

      对于每一个 1 

        用 f(i)表示 i 之前有多少个 0 ,用 g(i)表示 i 之后有多少个 0

      接下来就将答案集中在 1 中了。我们处理出  f(i)* g (i) 的前缀和,存入树状数组,那么就是区间查询了。

      再然后,我们特判边界处的 1 。具体如下:

    1. 区间中不存在 1,那就不需要处理了。

    2. 区间中只有一个 1,那就直接算。

    3. 区间中的 1 太多了,我们找出最左边的 1 与最右边的 1 。对它们的贡献做特殊处理。


      对于修改:

      我们们分两种情况处理:

          首先需要找到当前位置的前驱与后继的 1 。(并不包含该点)

       1. 0 -> 1 ,更新前驱与后继, 将该位置计入贡献。

       2. 1 -> 0 ,更新前驱与后继, 将该位置的贡献删去。

      接下来还有一种特殊情况:不存在前驱或后继 !

        为了避免大量分类讨论,我们在区间左端与右端加设一个位置,并为该位置上的数标记为 1 ,

        在整个询问与回答过程中都将其与其它的数当做一个整体,反正也不会被询问到。

    下面是我敲的代码,并不保证正确性!!!额

     

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 using namespace std;
      4 int n,k,m,a[100050];
      5 int opt,x,y,howne[100050];
      6 ll ans,sum,f[100050],g[100050];
      7 ll c[100050],wr;
      8 int read()
      9 {
     10     int w=0;
     11     char ch=getchar();
     12     while(ch<'0'||ch>'9')
     13         ch=getchar();
     14     while(ch>='0'&&ch<='9')
     15     {
     16         w=w*10+ch-48;
     17         ch=getchar();
     18     }
     19     return w;
     20 }
     21 void calc_pushans(int u,ll v)
     22 {
     23     while(u<=n)
     24     {
     25         c[u]+=v;
     26         u+=u&-u;
     27     }
     28 }
     29 void calc_pushowne(int u,int v)
     30 {
     31     while(u<=n)
     32     {
     33         howne[u]+=v;
     34         u+=u&-u;
     35     }
     36 }
     37 ll calc_askans(int u)
     38 {
     39     if(!u)    return 0;
     40     ll tmp=0;
     41     while(u)
     42     {
     43         tmp+=c[u];
     44         u-=u&-u;
     45     }
     46     return tmp;
     47 }
     48 int calc_askhowne(int u)
     49 {
     50     if(!u)    return 0;
     51     int tmp=0;
     52     while(u)
     53     {
     54         tmp+=howne[u];
     55         u-=u&-u;
     56     }
     57     return tmp;
     58 }
     59 void Dosomethingfirst()
     60 {
     61     for(int i=n+1;i>=1;--i)
     62         a[i]=a[i-1];
     63     sum=1;n+=2;a[1]=a[n]=1;
     64     for(int i=1;i<=n;++i)
     65     {
     66         if(a[i])
     67         {
     68             f[i]=sum;
     69             sum=1;
     70         }
     71         else
     72             ++sum;
     73     }
     74     sum=1;
     75     for(int i=n;i>=1;--i)
     76     {
     77         if(a[i])
     78         {
     79             g[i]=sum;
     80             calc_pushans(i,g[i]*f[i]);
     81             sum=1;
     82         }
     83         else
     84             ++sum;
     85     }
     86 }
     87 int  findpre(int l,int r)
     88 {
     89     if(a[l])
     90         return l;
     91     int v=calc_askhowne(l);
     92     while(l<r)
     93     {
     94         int mid=(l+r+1)>>1;
     95         if(calc_askhowne(mid)==v)
     96             l=mid;
     97         else
     98             r=mid-1;
     99     }
    100     return ++l;
    101 }
    102 int findaft(int l,int r)
    103 {
    104     int v=calc_askhowne(r);
    105     while(l<r)
    106     {
    107         int mid=(l+r)>>1;
    108         if(calc_askhowne(mid)==v)
    109             r=mid;
    110         else
    111             l=mid+1;
    112     }
    113     return l;
    114 }
    115 void calc()
    116 {
    117     Dosomethingfirst();
    118     while(m--)
    119     {
    120         opt=read();
    121         x=read();
    122         ++x;
    123         if(opt==1)
    124         {
    125             a[x]^=1;
    126             int l=findaft(1,x-1);
    127             int r=findpre(x+1,n);
    128             calc_pushans(l,-f[l]*g[l]);
    129             calc_pushans(r,-f[r]*g[r]);
    130             if(a[x]==0)
    131             {
    132                 calc_pushowne(x,-1);
    133                 g[l]=f[r]=r-l;
    134                 calc_pushans(x,-f[x]*g[x]);
    135                 f[x]=g[x]=0;
    136             }
    137             else
    138             {
    139                 calc_pushowne(x,1);
    140                 f[x]=g[l]=x-l;
    141                 g[x]=f[r]=r-x;
    142                 calc_pushans(x,f[x]*g[x]);
    143             }
    144             calc_pushans(l,f[l]*g[l]);
    145             calc_pushans(r,f[r]*g[r]);
    146         }
    147         else if(opt==2)
    148         {
    149             y=read();++y;
    150             ans=(ll)(y-x+1ll)*(ll)(y-x+2)/2;
    151             int l=findpre(x,y);
    152             int r=findaft(x,y);
    153             if(calc_askhowne(y)==calc_askhowne(x-1))
    154                 wr=0;
    155             else if(l==r)
    156                 wr=(ll)(y-l+1ll)*(l-x+1ll);
    157             else
    158             {
    159                 wr=calc_askans(y)-calc_askans(x-1);
    160                 wr-=(f[l]*g[l]+f[r]*g[r]);
    161                 wr+=((ll)(l-x+1ll)*g[l]+f[r]*(ll)(y-r+1ll));
    162             }
    163             printf("%lld
    ",ans-wr);
    164         }
    165     }
    166 }
    167 int main()
    168 {
    169     scanf("%d",&n);
    170     for(int i=1;i<=n;++i)
    171         a[i]=read();
    172     scanf("%d",&m);
    173     calc();
    174     return 0;
    175 }
    代码

    151

      

  • 相关阅读:
    Python inspect
    常见漏洞解析
    Linux安装常见问题
    Linux下查看系统信息
    (转)微信网页扫码登录的实现
    设计模式--六大原则
    Git 操作常用命令
    Scrapy工作原理
    PHP多维数组转一维
    归并排序(Python实现)
  • 原文地址:https://www.cnblogs.com/wyher/p/9803827.html
Copyright © 2020-2023  润新知