hdu1754splaytree区间查询
以前用线段树做的题。。发现splay好神奇
splay的区间查询就是把那个区间移到两个节点之间进行操作即可,同时每次rotate不要忘记pushup
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define maxn 200050 int pre[maxn],ch[maxn][2],size[maxn],Max[maxn],nums[maxn],keys[maxn],tot,root; int a[maxn],n,q; inline void pushup(int r){ Max[r]=max(max(Max[ch[r][0]],Max[ch[r][1]]),keys[r]); size[r]=size[ch[r][0]]+size[ch[r][1]]+1; } inline void newnode(int &r,int fa,int val){ r=++tot; ch[r][0]=ch[r][1]=0; size[r]=1; Max[r]=nums[r]=keys[r]=val; pre[r]=fa; } void build(int &r,int L,int R,int fa){ if(L>R) return; int mid=L+R>>1; newnode(r,fa,a[mid]); build(ch[r][0],L,mid-1,r); build(ch[r][1],mid+1,R,r); pushup(r); } void init(){ root=tot=0; ch[root][0]=ch[root][1]=size[root]=pre[root]=0; newnode(root,0,-1);newnode(ch[root][1],root,-1); build(ch[ch[root][1]][0],1,n,ch[root][1]); pushup(ch[root][1]); pushup(root); } void rotate(int x,int kind){ int fa=pre[x]; ch[fa][!kind]=ch[x][kind]; pre[ch[x][kind]]=fa; pre[x]=pre[fa]; if(pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa]=x; pre[fa]=x; ch[x][kind]=fa; pushup(fa);pushup(x); } void splay(int r,int goal){ while(pre[r]!=goal){ if(pre[pre[r]]==goal){ rotate(r,ch[pre[r]][0]==r); } else { int fa=pre[r]; int kind=ch[pre[fa]][0]==fa; if(ch[fa][kind]==r){ rotate(r,!kind); rotate(r,kind); } else { rotate(fa,kind); rotate(r,kind); } } } pushup(r); if(goal==0) root=r; } int getth(int r,int pos){ int t=size[ch[r][0]]+1; if(t==pos) return r; else if(t<pos) return getth(ch[r][1],pos-t); else return getth(ch[r][0],pos); } void update(int pos,int val){ int r=getth(root,pos); splay(r,0); Max[root]=nums[root]=keys[root]=val; pushup(root); } int query(int l,int r){ int L=getth(root,l),R=getth(root,r); splay(L,0); splay(R,root); return Max[ch[ch[root][1]][0]]; } void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d key = %2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],keys[x]); Treavel(ch[x][1]); } } void debug() { printf("root:%d\n",root); Treavel(root); } int main(){ while(scanf("%d%d",&n,&q)==2){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); init(); int a,b; char op[5]; while(q--){ scanf("%s%d%d",&op,&a,&b); if(op[0]=='U') update(a+1,b); else printf("%d\n",query(a,b+2)); //debug(); } } return 0; }