zoukankan      html  css  js  c++  java
  • [Bjoi2018]二进制

    题解:

    首先发现性质

    只有1个1的区间 或者 奇数个1且0的个数少于2这个区间是不合法的

    然后这个东西暴力是比较好处理的

    刚开始写的比较傻逼,分几种情况

    先把0,1缩在一起

    1.k1个0+1+k2个0

    2.k1个1+0+k2个1 其中k1+k2是奇数

    3.1之内单独1

    4.0+奇数1

    然后这样挺烦的

    最讨厌写这种很容易漏掉的分类套路了。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define dep(i,t,h) for (int i=t;i>=h;i--) 
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define ll long long
    const int N=2e5;
    int a[N],n,m,b[N],c[N],d[N],f[N];
    IL ll js(int l)
    {
      ll cnt=0; int jl=0;
      rep(k,1,l) if (b[k]==1) cnt++;
      b[0]=b[1]^1;
      rep(k,1,l)
        if (b[k]!=b[k-1]) c[++jl]=b[k],d[jl]=1;
        else d[jl]++;
      rep(i,1,jl)
        if (c[i]==1)
        {
          cnt+=f[d[i]];
          if (i>1) cnt+=(d[i]+1)/2;
          if (i<jl) cnt+=(d[i]+1)/2;
        }
      d[0]=d[jl+1]=0;
      rep(i,1,jl)
        if (c[i]==1)
        {
          if (d[i]==1) cnt+=1ll*d[i-1]*d[i+1];
          cnt+=max(d[i-1]-1,0);
          cnt+=max(d[i+1]-1,0);
        }
      rep(i,2,jl-1)
        if (c[i]==0&&d[i]==1)
        {
          cnt+=((d[i-1]+1)/2)*(d[i+1]/2)+(d[i-1]/2)*((d[i+1]+1)/2);
        }
      return 1ll*l*(l+1)/2-cnt;
    }
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n;
      rep(i,1,n) cin>>a[i];
      rep(i,1,5000)
        rep(j,3,i)
          if (j%2==1) f[i]+=i-j+1;
      cin>>m;
      rep(i,1,m)
      {
        int kk,x,y;
        cin>>kk;
        if (kk==1)
        {
          cin>>x; a[x]^=1;
        } else
        {
          cin>>x>>y;
          int len=y-x+1;
          rep(j,x,y) b[j-x+1]=a[j];
          cout<<js(len)<<endl;
        }
      }
      return 0;
    }

    我们考虑dp

    $f[i][[6]$分别对应

    0:0个0,奇数个1

    1:0个0,偶数个0

    2:1个0,奇数个0

    3:1个0,偶数个0

    4:1个1,任意0

    5:0个1,任意0

    写之前觉得挺烦的 写了发现好像挺好写 比上面那个不知道好写到哪里去了

    然后因为带修改,所以是动态dp

    链上动态dp用线段树

    树上动态dp用动态链分治(怎么随便做做到这么多动态dp。。)

    考虑用线段树维护

    我们得再用一维 表示这个是左边还是右边还是全部

    另外注意一下这样我们重复计数了 就是两种情况都满足的时候

    所以我们要01/10 以及1单独出现的

    但其实1单独出现的时候值是我们给的 所以直接给1不给2就行了

    但我写之前没想这个所以给了2然后用树状数组再维护了一下1的个数

    注意维护01/10的时候一个位置能影响两边

    除了updata其他都是模板

    updata只要思路清晰还是挺好写的

    所以这东西好像并不难写??

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define me(x) memset(x,0,sizeof(x))
    #define ll long long
    #define mid ((h+t)>>1)
    #define lowbit(x) (x&(-x))
    namespace IO{
      char ss[1<<24],*A=ss,*B=ss;
      IL char gc()
      {
          return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
      }
      template<class T>void read(T &x)
      {
          rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
          while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
      }
      char sr[1<<24],z[20]; int Z,C=-1;
      template<class T>void wer(T x)
      {
          if (x<0) sr[++C]='-',x=-x;
          while (z[++Z]=x%10+48,x/=10);
          while (sr[++C]=z[Z],--Z);
      }
      IL void wer1()
      {
          sr[++C]=' ';
      }
      IL void wer2()
      {
          sr[++C]='
    ';
      }
      template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;} 
      template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
      template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
      template<class T>IL T MIN(T x,T y) {return x<y?x:y;}
    };
    const int INF=1e9;
    const int N=1e5+1e4;
    using namespace IO;
    vector<int> ve;
    struct re{
        ll a[3][6],b;
    };
    struct sgt{
        ll f[N*4][3][6],g[N*4];
        re updata(ll x[3][6],ll y[3][6])
        {
            ll g[3][6]={},ans=0;
            ans+=x[1][0]*(y[0][1]+y[0][3]);
            ans+=x[1][1]*(y[0][0]+y[0][2]);
            ans+=x[1][2]*y[0][1];
            ans+=x[1][3]*y[0][0];
            ans+=x[1][4]*y[0][5];
            ans+=x[1][5]*y[0][4];
            g[0][0]=x[0][0]+x[2][0]*y[0][1]+x[2][1]*y[0][0];
            g[0][1]=x[0][1]+x[2][0]*y[0][0]+x[2][1]*y[0][1];
            g[0][2]=x[0][2]+x[2][0]*y[0][3]+x[2][1]*y[0][2]
            +x[2][2]*y[0][1]+x[2][3]*y[0][0];
            g[0][3]=x[0][3]+x[2][0]*y[0][2]+x[2][1]*y[0][3]
            +x[2][2]*y[0][0]+x[2][3]*y[0][1];
            g[0][4]=x[0][4]+x[2][4]*y[0][5]+x[2][5]*y[0][4];
            g[0][5]=x[0][5]+x[2][5]*y[0][5];
            g[1][0]=y[1][0]+y[2][0]*x[1][1]+y[2][1]*x[1][0];
            g[1][1]=y[1][1]+y[2][0]*x[1][0]+y[2][1]*x[1][1];
            g[1][2]=y[1][2]+y[2][0]*x[1][3]+y[2][1]*x[1][2]
            +y[2][2]*x[1][1]+y[2][3]*x[1][0];
            g[1][3]=y[1][3]+y[2][0]*x[1][2]+y[2][1]*x[1][3]
            +y[2][2]*x[1][0]+y[2][3]*x[1][1];
            g[1][4]=y[1][4]+y[2][4]*x[1][5]+y[2][5]*x[1][4];
            g[1][5]=y[1][5]+y[2][5]*x[1][5];
            g[2][0]=x[2][0]*y[2][1]+x[2][1]*y[2][0];
            g[2][1]=x[2][0]*y[2][0]+x[2][1]*y[2][1];
            g[2][2]=x[2][2]*y[2][1]+x[2][3]*y[2][0]
            +x[2][0]*y[2][3]+x[2][1]*y[2][2];
            g[2][3]=x[2][2]*y[2][0]+x[2][3]*y[2][1]
            +x[2][0]*y[2][2]+x[2][1]*y[2][3];
            g[2][4]=x[2][4]*y[2][5]+x[2][5]*y[2][4];
            g[2][5]=x[2][5]*y[2][5];
            re k;
            memcpy(k.a,g,sizeof(g)); k.b=ans;
            return k;
        }
        void change(int x,int h,int t,int pos,int k)
        {
            if (h==t)
            {
                if (k==1)
                {
                    rep(i,0,2)
                    {
                      f[x][i][0]=f[x][i][4]=1;
                      f[x][i][1]=f[x][i][2]=f[x][i][3]=f[x][i][5]=0;
                    }
                    g[x]=2;
                } else
                {
                    rep(i,0,2)
                    {
                        f[x][i][3]=f[x][i][5]=1;
                        f[x][i][0]=f[x][i][1]=f[x][i][2]=f[x][i][4]=0;
                    }
                    g[x]=0;
                }
                return;
            }
            if (pos<=mid) change(x*2,h,mid,pos,k);
            else change(x*2+1,mid+1,t,pos,k);
            re kk=updata(f[x*2],f[x*2+1]);
            memcpy(f[x],kk.a,sizeof(kk.a)); g[x]=kk.b+g[x*2]+g[x*2+1];
        }
        void query(int x,int h,int t,int h1,int t1)
        {
            if (h1<=h&&t<=t1)
            {
                ve.push_back(x); return;
            }
            if (h1<=mid) query(x*2,h,mid,h1,t1);
            if (mid<t1) query(x*2+1,mid+1,t,h1,t1);
        }
        ll query2(int x,int h,int t,int h1,int t1)
        {
            ve.clear();
            query(x,h,t,h1,t1);
            ll now[3][6],ans=0;
            for (int i=0;i<ve.size();i++) ans+=g[ve[i]];
            memcpy(now,f[ve[0]],sizeof(f[ve[0]]));
            for (int i=1;i<ve.size();i++)
            {
                re k=updata(now,f[ve[i]]);
                memcpy(now,k.a,sizeof(k.a)); ans+=k.b;
            }
            return ans;
        }
    }S;
    int a[N],n,m;
    struct sgt2{
        int sum[N];
        IL void c(int x,int t) { for(;x<=n;x+=lowbit(x)) sum[x]+=t;};
        IL int d(int x) {int ans=0; for (;x>0;x-=lowbit(x)) ans+=sum[x]; return ans;}
        IL int q(int h,int t) {return d(t)-d(h-1);}
    }S1,S2;
    int main()
    {
        read(n);
        rep(i,1,n) read(a[i]);
        rep(i,1,n)
        { 
          S.change(1,1,n,i,a[i]);
          if (a[i]==1) S1.c(i,1);
          if (i!=n&&a[i]^a[i+1]==1) S2.c(i,1);
        }
        read(m);
        rep(i,1,m)
        {
            int kk,x,y;
            read(kk);
            if (kk==2)
            {
                read(x); read(y);
                wer(1ll*(y-x+1)*(y-x+2)/2-(S.query2(1,1,n,x,y)-S1.q(x,y)-S2.q(x,y-1)));
                wer2();
            } else
            {
                read(x);
                if (x!=n&&a[x]^a[x+1]==1) S2.c(x,-1);
                if (a[x]==1) S1.c(x,-1);
                if (x!=1&&a[x-1]^a[x]==1) S2.c(x-1,-1);
                a[x]^=1;
                if (a[x]==1) S1.c(x,1);
                if (x!=n&&a[x]^a[x+1]==1) S2.c(x,1);
                if (x!=1&&a[x-1]^a[x]==1) S2.c(x-1,1);
                S.change(1,1,n,x,a[x]);
            }
        }
        fwrite(sr,1,C+1,stdout);
        return 0;
    }
  • 相关阅读:
    BZOJ 1207
    Poj 2096 Collecting Bugs (概率DP求期望)
    HDU 5159 Card (概率求期望)
    HDU 4649 Professor Tian (概率DP)
    HDU 4652 Dice (概率DP)
    HDU5001 Walk(概率DP)
    C++中的 Round(),floor(),ceil()
    HDU 5245 Joyful(概率题求期望)
    poj 3071 Football (概率DP水题)
    关于一个群号分解的最大质数的求法
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/10012450.html
Copyright © 2011-2022 走看看