POJ 1754 Splay
单点更新,区间最值,用来练Splay刚好。
将位置作为排序的规则,利用Splay不会改变顺序的特点,求某一段区间[l,r]的最值时,将l-1伸展到根,将r+1伸展到l-1的右子树,这时r+1的左子树就是要求的区间。维护一个最值即可。
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int N=200100,INF=0x3f3f3f3f; int t[N][2],fa[N],id,root; int data[N],res[N]; void pushup(int x){ res[x]=max(res[t[x][0]],res[t[x][1]]); res[x]=max(data[x],res[x]); } inline void Rotate(int x,int w){//0:左旋 1:右旋 int y=fa[x]; t[y][!w]=t[x][w]; if(t[x][w]) fa[t[x][w]]=y; fa[x]=fa[y]; if(fa[y]) t[fa[y]][t[fa[y]][1]==y]=x; t[x][w]=y; fa[y]=x; pushup(y); pushup(x); } void Splay(int x,int y){ while(fa[x]!=y){ if(t[fa[x]][0]==x) Rotate(x,1); else Rotate(x,0); } if(y==0) root=x; } void newnode(int x,int v){ t[x][0]=t[x][1]=0; fa[x]=x-1; res[x]=data[x]=v; t[x-1][1]=x; } void updata(int x,int v){ x++; data[x]=v; Splay(x,0); pushup(x); } int Q(int x,int y){ y+=2; Splay(x,0); Splay(y,x); return res[t[y][0]]; } int main(){ char op[2]; int x,v,n,m,i; while(scanf("%d%d",&n,&m)!=EOF){ newnode(1,-INF); for(i=1;i<=n;i++){ scanf("%d",&v); newnode(i+1,v); } newnode(n+2,-INF); for(i=n+2;i;i--) pushup(i); root=1; while(m--){ scanf("%s%d%d",op,&x,&v); if(op[0]=='U') updata(x,v); else printf("%d\n",Q(x,v)); } } return 0; }