1. 程式人生 > >bzoj1858[Scoi2010]序列操作

bzoj1858[Scoi2010]序列操作

同時存在 [1] 在那 zoj clas 操作 .com com 很好

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858

十分普通的線段樹。調了好久……

記錄一下0的信息,在reverse的時候比較方便。

1.把修改和pushdown裏要用到的東西都寫在一個函數裏比較方便。別忘了改標記。

  一開始沒有把改標記寫在那個函數裏,結果忘了在pushdown的時候下傳rev的標記。

2.修改操作很簡單。可以把標記規定成rev和b不同時存在、b[0]和b[1]不同時存在,就很好了。

3.三目運算符要整個括起來。

4.rev標記是^=1。

#include<iostream>
#include<cstdio>
#include
<cstring> using namespace std; const int N=1e5+5; int n,m,tot=1,L,R; bool c[N]; struct Node{ int ls,rs,cd; bool b[2],rev; int l[2],r[2],len[2],sum; }a[N<<1]; int rdn() { int ret=0;char ch=getchar(); while(ch>9||ch<0)ch=getchar(); while(ch<=9&&ch>=
0)(ret*=10)+=ch-0,ch=getchar(); return ret; } void pushup(int cr) { int ls=a[cr].ls,rs=a[cr].rs; a[cr].sum=a[ls].sum+a[rs].sum; for(int d=0;d<=1;d++) { a[cr].l[d]=a[ls].l[d]+(a[ls].l[d]==a[ls].cd?a[rs].l[d]:0);//括起來 a[cr].r[d]=a[rs].r[d]+(a[rs].r[d]==a[rs].cd?a[ls].r[d]:0
); a[cr].len[d]=max(max(a[ls].len[d],a[rs].len[d]),a[ls].r[d]+a[rs].l[d]); } } void build(int l,int r,int cr) { a[cr].cd=r-l+1; if(l==r){ a[cr].l[c[l]]=a[cr].r[c[l]]=a[cr].len[c[l]]=1; a[cr].sum=c[l];return; } int mid=((l+r)>>1); a[cr].ls=++tot;build(l,mid,tot); a[cr].rs=++tot;build(mid+1,r,tot); pushup(cr); } void mdf(int k,int d) { a[k].b[d]=1;a[k].b[!d]=0;a[k].rev=0;//b[0]和b[1]不同時存在 a[k].sum=a[k].cd*d; a[k].len[d]=a[k].l[d]=a[k].r[d]=a[k].cd; a[k].len[!d]=a[k].l[!d]=a[k].r[!d]=0; } void rv(int k) { a[k].rev^=1;//和mdf一樣,把下傳標記寫在函數裏 且是^=1 if(a[k].b[0]||a[k].b[1])a[k].rev=0,swap(a[k].b[0],a[k].b[1]);//rev和b不同時存在 a[k].sum=a[k].cd-a[k].sum;swap(a[k].len[1],a[k].len[0]); swap(a[k].l[0],a[k].l[1]);swap(a[k].r[0],a[k].r[1]); } void pushdown(int cr) { if(!a[cr].ls)return; int ls=a[cr].ls,rs=a[cr].rs; if(a[cr].rev) {a[cr].rev=0;rv(ls);rv(rs);a[cr].rev=0;} if(a[cr].b[0]||a[cr].b[1]) {int d=a[cr].b[1];a[cr].b[d]=0;mdf(ls,d);mdf(rs,d);} } void mdfy(int l,int r,int cr,int d) { if(l>=L&&r<=R){mdf(cr,d);return;} pushdown(cr); int mid=((l+r)>>1); if(mid>=L)mdfy(l,mid,a[cr].ls,d); if(mid<R)mdfy(mid+1,r,a[cr].rs,d); pushup(cr); } void rever(int l,int r,int cr) { if(l>=L&&r<=R){ rv(cr);return; } pushdown(cr); int mid=((l+r)>>1); if(mid>=L)rever(l,mid,a[cr].ls); if(mid<R)rever(mid+1,r,a[cr].rs); pushup(cr); } int query(int l,int r,int cr) { if(l>=L&&r<=R)return a[cr].sum; pushdown(cr); int mid=((l+r)>>1),ret=0; if(mid>=L)ret+=query(l,mid,a[cr].ls); if(mid<R)ret+=query(mid+1,r,a[cr].rs); return ret; } int lnk(int l,int r,int cr) { if(l>=L&&r<=R)return a[cr].len[1]; pushdown(cr); int mid=((l+r)>>1),ls=a[cr].ls,rs=a[cr].rs; if(mid<L)return lnk(mid+1,r,rs); if(mid>=R)return lnk(l,mid,ls); int tp=min(a[ls].r[1],mid-L+1)+min(a[rs].l[1],R-mid); return max(max(lnk(l,mid,ls),lnk(mid+1,r,rs)),tp);// } int main() { n=rdn();m=rdn();for(int i=1;i<=n;i++)c[i]=rdn(); build(1,n,1);int op; while(m--) { op=rdn();L=rdn()+1;R=rdn()+1; if(op<=1)mdfy(1,n,1,op); if(op==2)rever(1,n,1); if(op==3)printf("%d\n",query(1,n,1)); if(op==4)printf("%d\n",lnk(1,n,1)); } return 0; }

bzoj1858[Scoi2010]序列操作