[bzoj1251]序列终结者_splay
序列终结者 bzoj-1251
题目大意:给定一个长度为n的正整数序列,支持区间加,区间反转,查询区间最大值。所有元素开始都是0.
注释:$1\le n\le 5\cdot 10^4$,操作个数不多于$10^6$。
想法:splay模板题,splay在rotate时注意fa的从属,以及哨兵节点的边界情况。
最后,附上丑陋的代码... ...
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 50050 #define ls ch[p][0] #define rs ch[p][1] int n,m; int ch[N][2],f[N],siz[N],rt; int turn[N],delat[N],val[N],mx[N]; int get(int x){ return ch[f[x]][1]==x; } void pushup(int p) { if(p)siz[p]=siz[ls]+siz[rs]+1; mx[p]=max(mx[ls],mx[rs]); mx[p]=max(mx[p],val[p]); } void rotate(int x) { int y=f[x],z=f[y],k=get(x); ch[y][k]=ch[x][k^1];f[ch[y][k]]=y;ch[x][k^1]=y;f[y]=x;f[x]=z; if(z) ch[z][ch[z][1]==y]=x; pushup(y),pushup(x); if(rt==y)rt=x; } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;rotate(x)) if(f[fa]!=y) rotate((get(x)==get(fa)) ? fa : x); } void pushdown(int p) { int t=delat[p]; if(t) { delat[p]=0; if(ls)delat[ls]+=t, mx[ls]+=t, val[ls]+=t; if(rs)delat[rs]+=t, mx[rs]+=t, val[rs]+=t; } if(turn[p]) { turn[p]=0; swap(ls,rs); turn[ls]^=1;turn[rs]^=1; } //pushup(p); } void build(int fa,int l,int r) { if(l>r)return; int mid=l+r>>1; ch[fa][mid>fa]=mid; siz[mid]=1; val[mid]=0; f[mid]=fa; build(mid,l,mid-1); build(mid,mid+1,r); pushup(mid); } int find(int x) { int p=rt; while(1) { pushdown(p); if(x<=siz[ls])p=ls; else { x-=siz[ls]+1; if(!x)return p; p=rs; } } } void reverse(int x,int p) { x=find(x); p=find(p); //pushup(x);pushup(p); splay(x,0); splay(p,rt); //pushup(x);pushup(p); turn[ls]^=1; } void update(int x,int p,int c) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); delat[ls]+=c; val[ls]+=c; mx[ls]+=c; //pushup(p); //pushup(x); } void querymax(int x,int p) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); printf("%d\n",mx[ls]); } int main() { scanf("%d%d",&n,&m); int i,opt,x,y,z; for(i=0;i<=n+2;i++)mx[i]=-100000000; build(0,1,n+2); rt=n+3>>1; for(i=1;i<=m;i++) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&y,&z); if(x>y)swap(x,y); update(x,y+2,z); } else if(opt==2) { scanf("%d%d",&x,&y); if(x>y)swap(x,y); reverse(x,y+2); } else { scanf("%d%d",&x,&y); if(x>y)swap(x,y); querymax(x,y+2); } } }
小结:这种题面上几乎就写着用平衡树的题,随便怎么样都行了吧qwq。
| 欢迎来原网站坐坐! >原文链接<