bzoj1858[Scoi2010]序列操作
Posted narh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1858[Scoi2010]序列操作相关的知识,希望对你有一定的参考价值。
题目: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 ",query(1,n,1)); if(op==4)printf("%d ",lnk(1,n,1)); } return 0; }
以上是关于bzoj1858[Scoi2010]序列操作的主要内容,如果未能解决你的问题,请参考以下文章