1. 程式人生 > >BZOJ1251: 序列終結者

BZOJ1251: 序列終結者

傳送門 oot ring class \n upd down oid pre

【傳送門:BZOJ1251】


簡要題意:

  給出一個長度為n的序列,有m個操作,3種操作:

  1 l r k將l到r的數增加k

  2 l r將l到r的數列翻轉

  3 l r求出l到r的最大值


題解:

  裸SPLAY,直接下放兩種標記,一種翻轉,另一種增加值

  而且對於求l到r的區間,我們需要l-1和r+1的節點,而且不能用到0這個敏感位置,所以建樹的時候,序列編號要從1到n+2


參考代碼:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include
<algorithm> #include<cmath> using namespace std; struct node { int son[2],f,mx,lazy,c,d; bool fz; }tr[51000];int root,len; void pushdown(int x) { int lc=tr[x].son[0],rc=tr[x].son[1]; if(lc!=0) tr[lc].mx+=tr[x].lazy,tr[lc].d+=tr[x].lazy,tr[lc].lazy+=tr[x].lazy;
if(rc!=0) tr[rc].mx+=tr[x].lazy,tr[rc].d+=tr[x].lazy,tr[rc].lazy+=tr[x].lazy; tr[x].lazy=0; } void reverse(int x) { tr[x].fz=false; swap(tr[x].son[0],tr[x].son[1]); int lc=tr[x].son[0],rc=tr[x].son[1]; tr[lc].fz^=1;tr[rc].fz^=1; } void update(int x) { int lc=tr[x].son[0
],rc=tr[x].son[1]; tr[x].mx=tr[x].d; if(lc!=0) tr[x].mx=max(tr[x].mx,tr[lc].mx); if(rc!=0) tr[x].mx=max(tr[x].mx,tr[rc].mx); tr[x].c=tr[lc].c+tr[rc].c+1; } void rotate(int x,int w) { int f=tr[x].f,ff=tr[f].f; int r,R; r=tr[x].son[w];R=f; tr[R].son[1-w]=r; if(r!=0) tr[r].f=R; r=x;R=ff; if(tr[R].son[0]==f) tr[R].son[0]=r; else tr[R].son[1]=r; tr[r].f=R; r=f;R=x; tr[R].son[w]=r; tr[r].f=R; update(f); update(x); } int tmp[51000],s; void splay(int x,int rt) { int i=x;s=0; while(tr[i].f!=rt) { tmp[++s]=i; i=tr[i].f; } tmp[++s]=i; while(s!=0) { i=tmp[s--]; if(tr[i].fz==true) reverse(i); if(tr[i].lazy!=0) pushdown(i); } while(tr[x].f!=rt) { int f=tr[x].f,ff=tr[f].f; if(ff==rt) { if(tr[f].son[0]==x) rotate(x,1); else rotate(x,0); } else { if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);continue;} if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);continue;} if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);continue;} if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);continue;} } } if(rt==0) root=x; } int bt(int l,int r) { if(l>r) return 0; int now=++len; tr[now].mx=tr[now].lazy=tr[now].d=0; tr[now].lazy=false; int mid=(l+r)/2; tr[now].son[0]=bt(l,mid-1);tr[now].son[1]=bt(mid+1,r); int lc=tr[now].son[0],rc=tr[now].son[1]; if(lc!=0) tr[lc].f=now; if(rc!=0) tr[rc].f=now; tr[now].c=tr[lc].c+tr[rc].c+1; return now; } int finddizhi(int k) { int x=root; while(1) { if(tr[x].fz==true) reverse(x); if(tr[x].lazy!=0) pushdown(x); int lc=tr[x].son[0],rc=tr[x].son[1]; if(k<=tr[lc].c) x=lc; else if(k>tr[lc].c+1){k-=tr[lc].c+1;x=rc;} else break; } return x; } void add(int l,int r,int k) { int lc=finddizhi(l-1),rc=finddizhi(r+1); splay(lc,0);splay(rc,lc); int x=tr[rc].son[0]; tr[x].mx+=k; tr[x].d+=k; tr[x].lazy+=k; splay(x,0); } void fanzhuan(int l,int r) { int lc=finddizhi(l-1),rc=finddizhi(r+1); splay(lc,0);splay(rc,lc); int x=tr[rc].son[0]; tr[x].fz^=1; splay(x,0); } void findmax(int l,int r) { int lc=finddizhi(l-1),rc=finddizhi(r+1); splay(lc,0);splay(rc,lc); int x=tr[rc].son[0]; printf("%d\n",tr[x].mx); } int main() { int n,m; scanf("%d%d",&n,&m); len=0;root=bt(1,n+2); for(int i=1;i<=m;i++) { int k,l,r,v; scanf("%d%d%d",&k,&l,&r);l++;r++; if(k==1) { int v; scanf("%d",&v); add(l,r,v); } if(k==2) fanzhuan(l,r); if(k==3) findmax(l,r); } return 0; }

BZOJ1251: 序列終結者