bzoj1858: [Scoi2010]序列操作
就是写数据结构啊。。就连线段树都写这么久啊。。
本来以为这题应该就是线段树的两个遗传标记的解决,应该跟splay差不多,结果这题不一样。
主要的难点就是遗传标记的下放了。对于这里的翻转标记,他的实际意义应该是改值,所以应该是两个改值操作,跟之前做过的一道区间增加和区间乘操作一样,一个操作会影响另一个操作,操作的顺序不同会改变值,也就是不满足交换律。
对于这个问题,我的做法是记录修改的时间,比较两种修改的顺序,然后有一个注意的地方,就是连续反转两次时,re^=1,re^=1,此时re变回0,也就是不反转,那么假如在两次反转中有一次改值的操作,那么第一次反转失效,所以当改值的时候,把反转清空就行了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct seq { int l,r,lc,rc; int sum[2],lie[2],lef[2],rig[2]; int re,ch,rt,ct; }tr[210000];int trlen; int a[110000]; void update(int now,int lc,int rc) { tr[now].sum[0]=tr[lc].sum[0]+tr[rc].sum[0]; tr[now].sum[1]=tr[lc].sum[1]+tr[rc].sum[1]; tr[now].lie[0]=max( max(tr[lc].lie[0],tr[rc].lie[0]) , tr[lc].rig[0]+tr[rc].lef[0] ); tr[now].lie[1]=max( max(tr[lc].lie[1],tr[rc].lie[1]) , tr[lc].rig[1]+tr[rc].lef[1] ); int t; t=tr[lc].r-tr[lc].l+1; if(tr[lc].lef[0]!=t)tr[now].lef[0]=tr[lc].lef[0]; else tr[now].lef[0]=tr[lc].lef[0]+tr[rc].lef[0]; if(tr[lc].lef[1]!=t)tr[now].lef[1]=tr[lc].lef[1]; else tr[now].lef[1]=tr[lc].lef[1]+tr[rc].lef[1]; t=tr[rc].r-tr[rc].l+1; if(tr[rc].rig[0]!=t)tr[now].rig[0]=tr[rc].rig[0]; else tr[now].rig[0]=tr[rc].rig[0]+tr[lc].rig[0]; if(tr[rc].rig[1]!=t)tr[now].rig[1]=tr[rc].rig[1]; else tr[now].rig[1]=tr[rc].rig[1]+tr[lc].rig[1]; } void mychud(int now,int k,int t) { tr[now].ch=k;tr[now].re=0;tr[now].ct=t; int d=tr[now].r-tr[now].l+1; tr[now].sum[k]=tr[now].lie[k]=tr[now].lef[k]=tr[now].rig[k]=d; tr[now].sum[1-k]=tr[now].lie[1-k]=tr[now].lef[1-k]=tr[now].rig[1-k]=0; } void myswap(int now,int t) { tr[now].re^=1;tr[now].rt=t; swap(tr[now].sum[0],tr[now].sum[1]); swap(tr[now].lie[0],tr[now].lie[1]); swap(tr[now].lef[0],tr[now].lef[1]); swap(tr[now].rig[0],tr[now].rig[1]); } void jicheng(int now,int lc,int rc) { if(tr[now].ct>tr[now].rt) { if(tr[now].re==1) { myswap(lc,tr[now].rt); myswap(rc,tr[now].rt); tr[now].re=0; } if(tr[now].ch!=-1) { mychud(lc,tr[now].ch,tr[now].ct); mychud(rc,tr[now].ch,tr[now].ct); tr[now].ch=-1; } } else { if(tr[now].ch!=-1) { mychud(lc,tr[now].ch,tr[now].ct); mychud(rc,tr[now].ch,tr[now].ct); tr[now].ch=-1; } if(tr[now].re==1) { myswap(lc,tr[now].rt); myswap(rc,tr[now].rt); tr[now].re=0; } } } //-----------basic----------------------- void add(int l,int now) { tr[now].sum[a[l]]=1;tr[now].sum[1-a[l]]=0; tr[now].lie[a[l]]=1;tr[now].lie[1-a[l]]=0; tr[now].lef[a[l]]=1;tr[now].lef[1-a[l]]=0; tr[now].rig[a[l]]=1;tr[now].rig[1-a[l]]=0; } void bt(int l,int r) { trlen++;int now=trlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=0; tr[now].re=0;tr[now].ch=-1; tr[now].rt=-1;tr[now].ct=-1; if(l==r)add(l,now); else { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); update(now,tr[now].lc,tr[now].rc); } } //-----------build tree------------ void change(int now,int l,int r,int k,int t) { if(tr[now].l==l&&tr[now].r==r){mychud(now,k,t);return ;} int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; jicheng(now,lc,rc); if(r<=mid) change(lc,l,r,k,t); else if(mid+1<=l)change(rc,l,r,k,t); else change(lc,l,mid,k,t), change(rc,mid+1,r,k,t); update(now,lc,rc); } void reverse(int now,int l,int r,int t) { if(tr[now].l==l&&tr[now].r==r){myswap(now,t);return ;} int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; jicheng(now,lc,rc); if(r<=mid) reverse(lc,l,r,t); else if(mid+1<=l)reverse(rc,l,r,t); else reverse(lc,l,mid,t), reverse(rc,mid+1,r,t); update(now,lc,rc); } //----------change----------- int asksum(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r)return tr[now].sum[1]; int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; jicheng(now,lc,rc); if(r<=mid) return asksum(lc,l,r); else if(mid+1<=l)return asksum(rc,l,r); else return asksum(lc,l,mid)+asksum(rc,mid+1,r); } int asklie(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r)return tr[now].lie[1]; int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; jicheng(now,lc,rc); if(r<=mid) return asklie(lc,l,r); else if(mid+1<=l)return asklie(rc,l,r); else return max( max(asklie(lc,l,mid),asklie(rc,mid+1,r)) , min(tr[lc].r-l+1,tr[lc].rig[1]) + min(r-tr[rc].l+1,tr[rc].lef[1]) ); } //---------ask------------ void dfs(int now) { if(tr[now].l==tr[now].r) { printf("%d ",tr[now].sum[0]==0?1:0); return ; } jicheng(now,tr[now].lc,tr[now].rc); dfs(tr[now].lc); dfs(tr[now].rc); } int main() { //freopen("operation.in","r",stdin); //freopen("operation.out","w",stdout); int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++)scanf("%d",&a[i]); trlen=0;bt(1,n); int op,x,y; for(int i=1;i<=m;i++) { scanf("%d%d%d",&op,&x,&y);x++;y++; if(op==0||op==1)change(1,x,y,op,i); else if(op==2)reverse(1,x,y,i); else if(op==3)printf("%d\n",asksum(1,x,y)); else if(op==4)printf("%d\n",asklie(1,x,y)); //dfs(1);printf("\n"); } } return 0; }
pain and happy in the cruel world.