题目描述:给定一个长度为 n 的初始为 0 的序列,m 个操作,包括区间维护、区间翻转、区间最大值查询。n ≤ 50000,m ≤ 100000。
伸展树模板题。每个节点加上两个标记,伸展时下传标记即可。
代码如下:
#include"stdio.h" #define Exchange(a,b) \ { \ typeof(a) __tmp_a=a; \ a=b,b=__tmp_a; \ } #define Max_Integer(a,b) \ ({ \ int __tmp_a=(a),__tmp_b=(b); \ __tmp_a>__tmp_b?__tmp_a:__tmp_b; \ }) struct SPLAY_TREE_NODE *NIL; struct SPLAY_TREE_NODE { int add,flag,key,mx,size; SPLAY_TREE_NODE *child[2]; SPLAY_TREE_NODE(int k,int s) { add=flag=mx=0; child[0]=child[1]=NIL; key=k; size=s; } void pushdown() { if(add!=0) { mx+=add; key+=add; if(child[0]!=NIL) child[0]->add+=add; if(child[1]!=NIL) child[1]->add+=add; add=0; } if(flag==1) { flag=0; Exchange(child[0],child[1]); if(child[0]!=NIL) child[0]->flag^=1; if(child[1]!=NIL) child[1]->flag^=1; } } }; void UpMax(SPLAY_TREE_NODE *now,SPLAY_TREE_NODE *end,int chi) { if(now==end) return; UpMax(now->child[chi],end,chi); now->mx=Max_Integer(now->key,Max_Integer(now->child[0]->add+now->child[0]->mx,now->child[1]->add+now->child[1]->mx)); } SPLAY_TREE_NODE* Splay(SPLAY_TREE_NODE *now,int rak) { SPLAY_TREE_NODE *Header=new SPLAY_TREE_NODE(0,now->size+1),*next,*SubTree[2]; SubTree[0]=Header; SubTree[1]=Header->child[1]=new SPLAY_TREE_NODE(0,rak); now->pushdown(); while(rak!=now->child[0]->size+1) { int chi=rak<now->child[0]->size+1?0:1; rak-=chi>0?now->child[0]->size+1:0; if((next=now->child[chi])==NIL) break; now->child[chi]=NIL; SubTree[chi]->child[chi]=now; now->size=SubTree[chi]->size-SubTree[chi]->child[1-chi]->size-1; SubTree[chi]=now; now=next; now->pushdown(); } SubTree[0]->child[0]=now->child[1]; SubTree[1]->child[1]=now->child[0]; UpMax(Header->child[1]->child[1],now->child[0],1); UpMax(Header->child[0],now->child[1],0); now->child[0]=Header->child[1]->child[1]; now->child[1]=Header->child[0]; now->mx=Max_Integer(now->child[0]->add+now->child[0]->mx,now->child[1]->add+now->child[1]->mx); now->size=now->child[0]->size+now->child[1]->size+1; return now; } SPLAY_TREE_NODE* Build(int left,int right) { if(left>=right) return NIL; int middle=(left+right)/2; SPLAY_TREE_NODE *now=new SPLAY_TREE_NODE(0,right-left); now->child[0]=Build(left,middle); now->child[1]=Build(middle+1,right); return now; } int main() { NIL=new SPLAY_TREE_NODE(0,0); NIL->child[0]=NIL->child[1]=NIL; NIL->mx=-0x80000000; SPLAY_TREE_NODE *now,*stroot; int k,l,m,n,r,v; scanf("%d %d",&n,&m); stroot=Build(1,n+1); while(m--) { scanf("%d %d %d",&k,&l,&r); if(l!=1) if(r!=n) stroot=Splay(stroot,l-1), stroot->child[1]=Splay(stroot->child[1],r-stroot->child[0]->size), now=stroot->child[1]->child[0]; else stroot=Splay(stroot,l-1), now=stroot->child[1]; else if(r!=n) stroot=Splay(stroot,r+1), now=stroot->child[0]; else now=stroot; switch(k) { case 1:scanf("%d",&v);now->add+=v;break; case 2:now->flag^=1;break; case 3:printf("%d\n",now->add+now->mx);break; } } return 0; }