------------!

题目背景

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

 

题目描述
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\n",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

  

posted @ 2018-10-17 14:13  Hevix  阅读(343)  评论(0编辑  收藏  举报