zoukankan      html  css  js  c++  java
  • bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572

    记一下:线段树占空间是$2^{ceil(log2(n))+1}$

    这个就是一个线段树区间操作题,各种标记的设置、转移都很明确,只要熟悉这类题应该说是没有什么难度的。

    由于对某区间set之后该区间原先待进行的取反操作失效(被覆盖),因此规定tag同时存在时set的标记先进行操作,这样对区间加上set标记时要去掉原有的取反标记。

    对于操作4,线段树上每个区间维护6个值,分别表示:该区间最多的连续0/1,从左侧数起/从右侧数起/其中任意位置。题目中不问连续0,为什么连续0也要维护呢?这是为了在进行取反操作时,O(1)完成标记的维护(直接交换对0、1维护的3个值就行了)。

    对于操作3,线段树上每个区间维护该区间1的个数。此时不需要额外记录0的个数,0的个数可以由区间总数-1的个数得到。

    规定:set的标记为-1时表示不需要set操作,为0/1时表示需要set为该标记的值。

    注意一点:对于取反的tag,每次取反操作的时候都是将tag取反,而不是置为1,不然在同一个位置取反两次就不对了。

    各个标记含义同普通线段树:当前节点已经操作,其所有(任意级的)子节点待操作。维护的时候转移都是递推,细的就不讲了,有点多,要细心比对。

    然而...

    感觉自己药丸啊...调了三个小时才调出来,各种各样诡异的错误...如果省选考这个肯定没法做了..

    幸好这个样例够强。。有一些奇怪的错误通过样例就查出来了,过了样例就1A了,不然真的不知道要调到什么时候。。。

    note:以下程序中打了注释的语句都是错过的。。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define mid ((l+r)>>1)
      5 #define lc (num<<1)
      6 #define rc (num<<1|1)
      7 using namespace std;
      8 struct Th
      9 {
     10     int a,b,c;
     11     bool d;//是否全部是1
     12     int len;
     13     Th(int aa=0,int bb=0,int cc=0,bool dd=1,int ll=0):a(aa),b(bb),c(cc),d(dd),len(ll){}
     14 };
     15 int num1[270000],maxnum[270000][2][3],settag[270000];
     16 bool revtag[270000];
     17 int n,m;
     18 //定义tag同时存在时settag先进行操作
     19 int a[100010];
     20 int L,R,x;
     21 //maxnum[][0/1][0/1/2]表示最多的连续0/1,接左侧/接右侧/中间
     22 void pd(int l,int r,int num)
     23 {
     24     if(settag[num]!=-1)
     25     {
     26         num1[lc]=settag[num]*(mid-l+1);
     27         maxnum[lc][0][0]=maxnum[lc][0][1]=maxnum[lc][0][2]=(1-settag[num])*(mid-l+1);
     28         maxnum[lc][1][0]=maxnum[lc][1][1]=maxnum[lc][1][2]=settag[num]*(mid-l+1);
     29         num1[rc]=settag[num]*(r-mid);
     30         maxnum[rc][0][0]=maxnum[rc][0][1]=maxnum[rc][0][2]=(1-settag[num])*(r-mid);
     31         maxnum[rc][1][0]=maxnum[rc][1][1]=maxnum[rc][1][2]=settag[num]*(r-mid);
     32         revtag[lc]=revtag[rc]=0;
     33         settag[lc]=settag[rc]=settag[num];
     34         settag[num]=-1;
     35     }
     36     if(revtag[num])
     37     {
     38         num1[lc]=mid-l+1-num1[lc];
     39         num1[rc]=r-mid-num1[rc];
     40         swap(maxnum[lc][0][0],maxnum[lc][1][0]);
     41         swap(maxnum[lc][0][1],maxnum[lc][1][1]);
     42         swap(maxnum[lc][0][2],maxnum[lc][1][2]);
     43         swap(maxnum[rc][0][0],maxnum[rc][1][0]);
     44         swap(maxnum[rc][0][1],maxnum[rc][1][1]);
     45         swap(maxnum[rc][0][2],maxnum[rc][1][2]);
     46         revtag[lc]^=1;revtag[rc]^=1;
     47         revtag[num]=0;
     48     }
     49 }
     50 void update(int l,int r,int num)
     51 {
     52     num1[num]=num1[lc]+num1[rc];
     53     maxnum[num][0][0]=maxnum[lc][0][0];
     54     if(num1[lc]==0)    maxnum[num][0][0]=(mid-l+1)+maxnum[rc][0][0];
     55     maxnum[num][0][1]=maxnum[rc][0][1];
     56     if(num1[rc]==0)    maxnum[num][0][1]=(r-mid)+maxnum[lc][0][1];
     57     maxnum[num][1][0]=maxnum[lc][1][0];
     58     if(num1[lc]==mid-l+1)    maxnum[num][1][0]=(mid-l+1)+maxnum[rc][1][0];
     59     maxnum[num][1][1]=maxnum[rc][1][1];
     60     if(num1[rc]==r-mid)    maxnum[num][1][1]=(r-mid)+maxnum[lc][1][1];
     61     maxnum[num][0][2]=max(max(maxnum[lc][0][2],maxnum[rc][0][2]),maxnum[lc][0][1]+maxnum[rc][0][0]);
     62     maxnum[num][1][2]=max(max(maxnum[lc][1][2],maxnum[rc][1][2]),maxnum[lc][1][1]+maxnum[rc][1][0]);
     63 }
     64 void build(int l,int r,int num)
     65 {
     66     if(l==r)
     67     {
     68         num1[num]=(a[l]==1);
     69         maxnum[num][0][0]=maxnum[num][0][1]=maxnum[num][0][2]=(a[l]==0);
     70         maxnum[num][1][0]=maxnum[num][1][1]=maxnum[num][1][2]=(a[l]==1);
     71         settag[num]=-1;
     72         return;
     73     }
     74     build(l,mid,lc);
     75     build(mid+1,r,rc);
     76     settag[num]=-1;update(l,r,num);
     77 }
     78 void setto(int l,int r,int num)
     79 {
     80     if(L<=l&&r<=R)
     81     {
     82         revtag[num]=0;settag[num]=x;
     83         num1[num]=x*(r-l+1);//mid-l+1
     84         maxnum[num][0][0]=maxnum[num][0][1]=maxnum[num][0][2]=(1-x)*(r-l+1);//mid-l+1
     85         maxnum[num][1][0]=maxnum[num][1][1]=maxnum[num][1][2]=x*(r-l+1);//mid-l+1
     86         return;
     87     }
     88     pd(l,r,num);
     89     if(L<=mid)    setto(l,mid,lc);
     90     if(mid<R)    setto(mid+1,r,rc);
     91     update(l,r,num);
     92 }
     93 void revx(int l,int r,int num)
     94 {
     95     if(L<=l&&r<=R)
     96     {
     97         revtag[num]^=1;
     98         num1[num]=r-l+1-num1[num];
     99         swap(maxnum[num][0][0],maxnum[num][1][0]);
    100         swap(maxnum[num][0][1],maxnum[num][1][1]);
    101         swap(maxnum[num][0][2],maxnum[num][1][2]);
    102         return;
    103     }
    104     pd(l,r,num);
    105     if(L<=mid)    revx(l,mid,lc);
    106     if(mid<R)    revx(mid+1,r,rc);
    107     update(l,r,num);
    108 }
    109 int query1(int l,int r,int num)
    110 {
    111     if(L<=l&&r<=R)    return num1[num];
    112     pd(l,r,num);
    113     int ans=0;
    114     if(L<=mid)    ans+=query1(l,mid,lc);
    115     if(mid<R)    ans+=query1(mid+1,r,rc);
    116     return ans;
    117 }
    118 Th query2(int l,int r,int num)
    119 {
    120     //if(L<=l&&r<=R)    return Th(maxnum[num][1][0],maxnum[num][1][1],maxnum[num][1][2],num1[num]==r-l+1,1);
    121     if(L<=l&&r<=R)    return Th(maxnum[num][1][0],maxnum[num][1][1],maxnum[num][1][2],num1[num]==r-l+1,r-l+1);//num1[num]==1
    122     pd(l,r,num);
    123     Th ans,t1,t2;
    124     if(L<=mid)    t1=query2(l,mid,lc);
    125     if(mid<R)    t2=query2(mid+1,r,rc);
    126     ans.a=t1.a;
    127     //if(t1.d||t1.len==0)    ans.a=t1.len+t2.a;
    128     if(t1.d)    ans.a=t1.len+t2.a;
    129     ans.b=t2.b;
    130     //if(t2.d||t2.len==0)    ans.b=t2.len+t1.b;
    131     if(t2.d)    ans.b=t2.len+t1.b;
    132     ans.c=max(max(t1.c,t2.c),t1.b+t2.a);
    133     ans.d=t1.d&&t2.d;
    134     ans.len=t1.len+t2.len;
    135     return ans;
    136 }
    137 int main()
    138 {
    139     int i,idx;Th ttt;
    140     scanf("%d%d",&n,&m);
    141     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    142     build(1,n,1);
    143     for(i=1;i<=m;i++)
    144     {
    145         scanf("%d%d%d",&idx,&L,&R);L++,R++;
    146         if(idx==0)    x=0,setto(1,n,1);
    147         else if(idx==1)    x=1,setto(1,n,1);
    148         else if(idx==2)    revx(1,n,1);
    149         else if(idx==3)    printf("%d
    ",query1(1,n,1));
    150         else if(idx==4)    {ttt=query2(1,n,1);printf("%d
    ",max(max(ttt.a,ttt.b),ttt.c));}
    151     }
    152     return 0;
    153 }
  • 相关阅读:
    Xposed学习一:初探
    drozer浅析三:命令实现与交互
    drozer源码学习二:info+scanner
    drozer源码学习:app
    android dalvik浅析一:解释器及其执行
    智能汽车安全风险及防护技术分析
    几维安全“把手伸向金融交易系统”
    几维安全携手苏宁易购,创造企业安全建设新模式
    传输协议不安全,数据泄露谁之过?——流量劫持技术分析
    【一周安全热点】黑客“撞库”破解抖音百万账户密码两月获利上百万元|美国佛罗里达州向勒索软件运营商支付60万美元赎金
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8525697.html
Copyright © 2011-2022 走看看