①学会了维护最大连续子序列,跟最长全0连续子序列其实差不多;我一开始做麻烦了(用了前缀和。。)。
一些需要注意的细节:
②插入新节点的时候要注意维护其儿子节点的父指针;
③pushdown的位置不是随便放的,它应该放在对该节点进行询问之前。
④覆盖标记应该设为无穷,而不是0;因为0也可能是需要覆盖的。
⑤翻转标记应该使用^=标记,而不是=。
#include<iostream> using namespace std; #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> struct SS{ SS * f,* c[2]; bool is_root; int size,data,sum,lmax,rmax,max; int lazy; bool flag; }*nil=new SS((SS){nil,nil,nil,0,0,0,0,-1E7,-1E7,-1E7}),*root=new SS((SS){nil,nil,nil,1,2,-1E6,-2E6,-1E6,-1E6,-1E6}); int T; inline void Out(SS * x){ //printf("%d(%d) ",x->data,T++); cout<<"("<<x->f->data<<")"<<x->data<<":"<<x->size<<"(Size) "<<x->sum<<"(Sum) "<<x->lmax<<"(Lmax) "<<x->rmax<<"(Rmax) "<<x->max<<"(Max)\n"; } inline void mtn(SS * x){ x->size=x->c[0]->size+x->c[1]->size+1; x->sum=x->c[0]->sum+x->c[1]->sum+x->data; x->lmax=max(x->c[0]->lmax,max(x->c[0]->sum+x->data,x->c[0]->sum+x->data+x->c[1]->lmax)); x->rmax=max(x->c[1]->rmax,max(x->c[1]->sum+x->data,x->c[1]->sum+x->data+x->c[0]->rmax)); x->max=max(x->data,max(x->lmax,max(x->rmax,max(x->c[0]->rmax+x->data,max(x->c[0]->rmax+x->data+x->c[1]->lmax,max(x->data+x->c[1]->lmax,max(x->c[0]->max,x->c[1]->max))))))); } inline void re_paint(SS * x){ if(x!=nil){ swap(x->c[0],x->c[1]); swap(x->lmax,x->rmax); x->flag^=1; } } inline void sa_paint(SS * x,int A){ if(x!=nil){ x->data=A; x->sum=A*x->size; x->lazy=A; if(A<0)x->lmax=x->rmax=x->max=A; else x->lmax=x->rmax=x->max=A*x->size; } } inline void pushdown(SS * x){ if(x->flag){ re_paint(x->c[0]); re_paint(x->c[1]); x->flag=0; } if(x->lazy!=-0x7fffffff){ sa_paint(x->c[0],x->lazy); sa_paint(x->c[1],x->lazy); x->lazy=-0x7fffffff; } } inline void out(SS * x){ if(x==nil)return; pushdown(x); out(x->c[0]); Out(x); out(x->c[1]); } inline void zig(SS * x,bool D){ SS * ftr=x->f; x->f=ftr->f; //cout<<x->data<<"->"<<x->c[0]->data<<" "<<x->c[1]->data<<"------>"<<ftr->data<<"->"<<ftr->c[0]->data<<" "<<ftr->c[1]->data<<endl; if(ftr->is_root)ftr->is_root=0,x->is_root=1; if(x->f->c[1]==ftr)x->f->c[1]=x; else x->f->c[0]=x; ftr->c[D]=x->c[!D]; ftr->c[D]->f=ftr; x->c[!D]=ftr; ftr->f=x; mtn(ftr); //cout<<"Zig:"<<x->data<<"->"<<x->c[0]->data<<" "<<x->c[1]->data<<"------>"<<ftr->data<<"->"<<ftr->c[0]->data<<" "<<ftr->c[1]->data<<endl; } inline void splay(SS * x){ /*cout<<"S:"; out(root);*/ for(bool D;!x->is_root;zig(x,D)){ D=x->f->c[1]==x; if(!x->f->is_root&&D==(x->f->f->c[1]==x->f))zig(x->f,D); } root=x; mtn(x);/* cout<<"Play\n"; out(root); cout<<"\n";*/ } inline void search(SS * x,int A){ //cout<<x->data<<endl; pushdown(x); while(x->c[0]->size!=A-1){ //cout<<"Search:"<<x->data<<","<<A<<"("<<x->size<<")"<<x->c[0]->data<<"("<<x->c[0]->size<<")\n"; if(x->c[0]->size>=A)x=x->c[0]; else A-=x->c[0]->size+1,x=x->c[1]; pushdown(x); } splay(x); } inline void open(int l,int L){//(l,r) //cout<<"Open:"<<l<<"->"<<L<<endl; search(root,l); //out(root); root=root->c[1]; root->is_root=1; search(root,L+1); } inline void close(){ mtn(root); root->is_root=0; root=root->f; mtn(root); } char * ptr=(char *)malloc(30000000); inline int in(){ bool flag=0; while(*ptr<'0'||*ptr>'9') if(*ptr++=='-') flag=1; int x=0; while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0'; if(flag)return -x; return x; } int main(){ freopen("seq2005.in","r",stdin); freopen("seq2005.out","w",stdout); root->c[0]=new SS((SS){root,nil,nil,0,1,-1E6,-1E6,-1E6,-1E6,-1E6}); root->lazy=-0x7fffffff; root->c[0]->lazy=-0x7fffffff; fread(ptr,1,30000000,stdin); SS * tmp; open(1,0); int posi,tot=in(),M=in(),c; while(tot--){ root->c[0]=new SS((SS){root,root->c[0],nil,0,0,in()}); root->c[0]->c[0]->f=root->c[0]; root->c[0]->lazy=-0x7fffffff; mtn(root->c[0]); } close(); while(M--){ while(*ptr<'A'||*ptr>'Z')++ptr; ptr+=2; switch(*ptr){ case 'S': posi=in()+1,tot=in(); open(posi,0); while(tot--){ root->c[0]=new SS((SS){root,root->c[0],nil,0,0,in()}); root->c[0]->c[0]->f=root->c[0]; root->c[0]->lazy=-0x7fffffff; mtn(root->c[0]); } close(); break; case 'L': posi=in(),tot=in(); open(posi,tot); root->c[0]=nil; close(); break; case 'K': ptr+=4; posi=in(),tot=in(); open(posi,tot); sa_paint(root->c[0],in()); close(); break; case 'V': posi=in(),tot=in(); open(posi,tot); re_paint(root->c[0]); close(); break; case 'T': ptr+=2; posi=in(),tot=in(); open(posi,tot); printf("%d\n",root->c[0]->sum); close(); break; case 'X': ptr+=5; printf("%d\n",root->max); break; }/* cout<<M<<":"; T=0; out(root); cout<<endl;*/ } }