bzoj1500 [NOI2005]维修数列
Posted liu_runda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500 [NOI2005]维修数列相关的知识,希望对你有一定的参考价值。
坑点:GET-SUM的第二个参数可以是0,这时直接输出0.(论1A和差点1A的区别)(没事反正这次是在cogs上交的我下次重写一遍bzoj上一定能1A)
最大子段和的处理需要对每棵子树维护一下最大前缀和,最大后缀和以及最大子段和(都不能为空)。把这些数据打包写成一个结构体就比较整洁了。
每个子树的数据=左子树+根节点+右子树,数据打包之后这两个‘+’本质是相同的操作。
然后就都是套路了,split一下,merge一下。。。
#include<cstdio> #include<algorithm> using namespace std; struct data{ int lmax,rmax,mmax,sum; void rev(){ swap(lmax,rmax); } data(){} data(int x){lmax=rmax=sum=mmax=x;} data(int x,int num){ sum=x*num; lmax=rmax=mmax=max(x,sum); } data operator +(const data &B)const{ data C; C.sum=sum+B.sum; C.lmax=max(lmax,sum+B.lmax);C.rmax=max(B.rmax,B.sum+rmax); C.mmax=max(max(mmax,B.mmax),rmax+B.lmax); return C; } }; const int maxn=500005; struct node{ int mk,mkt;//mkt==2:change mkt==1:reverse mkt==0:nothing data subtree,rtnode; node* ch[2],*prt; int sz; node(){} node(int x,node* p){ ch[0]=ch[1]=0;prt=p;mk=mkt=0; subtree=rtnode=data(x); } void setto(int x){ mkt=2;mk=x;rtnode=data(x);subtree=data(x,sz); } void rev(){ if(mkt==2)return; mkt^=1;subtree.rev(); } void update(){ subtree=rtnode;sz=1; if(ch[0])subtree=ch[0]->subtree+subtree,sz+=ch[0]->sz; if(ch[1])subtree=subtree+ch[1]->subtree,sz+=ch[1]->sz; } void pushdown(){ if(mkt==1){ swap(ch[0],ch[1]); if(ch[0])ch[0]->rev();if(ch[1])ch[1]->rev(); mkt=0; }else if(mkt==2){ if(ch[0])ch[0]->setto(mk);if(ch[1])ch[1]->setto(mk); mkt=0; } } }; node *root,*c0,*c1; node *kth(node *rt,int k){ rt->pushdown(); int lsz=(rt->ch[0])?rt->ch[0]->sz:0; if(k<=lsz)return kth(rt->ch[0],k); if(k==lsz+1)return rt; return kth(rt->ch[1],k-lsz-1); } inline int isch1(node *rt){return rt==(rt->prt->ch[1]);} void rot(node *rt,int t){ node *c=rt->ch[t],*p=rt->prt; rt->pushdown();c->pushdown(); if(!p)root=c; else p->ch[isch1(rt)]=c; c->prt=p; rt->ch[t]=c->ch[t^1]; if(c->ch[t^1])c->ch[t^1]->prt=rt; rt->prt=c;c->ch[t^1]=rt; rt->update();c->update(); } void splay(node* rt,node *ed){ node *p,*g; while((p=rt->prt)&&(g=p->prt)){ g->pushdown();p->pushdown(); if(p==ed)return; if(g==ed){rot(p,isch1(rt));return;} int t1=isch1(rt),t2=isch1(p); if(t1==t2){rot(g,t2);rot(p,t1);} else {rot(p,t1);rot(g,t2);} } if(ed==0&&p!=0){p->pushdown();rot(p,isch1(rt));} } void split(int l,int r){ splay(kth(root,l),0); c0=root->ch[0]; if(c0){c0->prt=0;root->ch[0]=0;root->update();} splay(kth(root,r-l+1),0); c1=root->ch[1]; if(c1){c1->prt=0;root->ch[1]=0;root->update();} } void split(int l){ if(l==0){ c1=root;c0=0;root=0;return; } splay(kth(root,l),0); c1=root->ch[1]; if(c1){c1->prt=0;root->ch[1]=0;root->update();} c0=root;root=0; } void merge3(){ splay(kth(root,1),0);root->ch[0]=c0; if(c0){c0->prt=root;root->update();} splay(kth(root,root->sz),0);root->ch[1]=c1; if(c1){c1->prt=root;root->update();} } void merge2(){ if(!c1)root=c0; else if(!c0)root=c1; else{ root=c1;splay(kth(root,1),0);root->ch[0]=c0;c0->prt=root;root->update(); } } void remove(int l,int r){ split(l,r);merge2(); } void reverse(int l,int r){ split(l,r);root->rev();root->pushdown();merge3(); } void change(int l,int r,int x){ split(l,r);root->setto(x);root->pushdown();merge3(); } void getsum(int l,int r){ if(l>r){printf("0\n");return;} split(l,r);printf("%d\n",root->subtree.sum);merge3(); } void maxsum(){printf("%d\n",root->subtree.mmax);} int seq[maxn]; void build(node* &rt,node *p,int l,int r){ if(l>r)return; int mid=(l+r)>>1; rt=new node(seq[mid],p); build(rt->ch[0],rt,l,mid-1);build(rt->ch[1],rt,mid+1,r); rt->update(); } void insert(int pos,int len){ split(pos);build(root,0,1,len);merge3(); } int main(){ // freopen("seq2005.in","r",stdin); // freopen("seq2005.out","w",stdout); int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",seq+i); build(root,0,1,n); char buf[20]; int x,y,z; for(int i=1;i<=m;++i){ scanf("%s",buf); if(buf[0]==‘I‘){ scanf("%d%d",&x,&y); for(int i=1;i<=y;++i)scanf("%d",seq+i); insert(x,y); }else if(buf[0]==‘D‘){ scanf("%d%d",&x,&y);remove(x,x+y-1); }else if(buf[0]==‘G‘){ scanf("%d%d",&x,&y);getsum(x,x+y-1); }else if(buf[0]==‘R‘){ scanf("%d%d",&x,&y);reverse(x,x+y-1); }else if(buf[2]==‘X‘){ maxsum(); }else { scanf("%d%d%d",&x,&y,&z);change(x,x+y-1,z); } } // fclose(stdin);fclose(stdout); return 0; }
以上是关于bzoj1500 [NOI2005]维修数列的主要内容,如果未能解决你的问题,请参考以下文章