HDU1754 I Hate It (Splay)

来源:互联网 发布:阳泉百度云计算 编辑:程序博客网 时间:2024/05/16 15:47

题意:中文题。。。

以前用线段树写过。。现在学Splay,也来写一下。。

用伸展树来进行单点更新和区间查询,单点更新就直接查选第k个直接查选到这个点然后再维护上去就可以了,,区间查选,因为这里是闭区间,所以要先把区间扩大一下(自己用手写下就知道),然后第k个找到左边界的点,旋转到根,找到右边界的点旋转到根的右子树,然后右边界的点的左子树就是要找的答案了。。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=222222;struct Node{Node *ch[2];Node *pre;int size,val,mx;}p[MAXN];int num[MAXN];int tot;Node *null=&p[0];Node *root;Node *new_Node(int val){Node *rt=&p[++tot];rt->val=val;rt->size=1;rt->ch[0]=null;rt->ch[1]=null;rt->pre=null;return rt;}void pushup(Node *rt){rt->mx=max(rt->val,max(rt->ch[0]->mx,rt->ch[1]->mx));rt->size=rt->ch[0]->size+rt->ch[1]->size+1;}Node *build(int l,int r){if(l>r)return null;Node *rt;int mid=(l+r)>>1;rt=new_Node(num[mid-1]);rt->ch[0]=build(l,mid-1);rt->ch[0]->pre=rt;rt->ch[1]=build(mid+1,r);rt->ch[1]->pre=rt;pushup(rt);return rt;}void Rotate(Node *x,int c){Node *y=x->pre;y->ch[!c]=x->ch[c];if(x->ch[c]!=null){x->ch[c]->pre=y;}x->pre=y->pre;if(y->pre!=null){if(y->pre->ch[0]==y)y->pre->ch[0]=x;elsey->pre->ch[1]=x;}x->ch[c]=y;y->pre=x;if(y==root)x=root;pushup(y);pushup(x);}void splay(Node *x,Node *f){while(x->pre!=f){if(x->pre->pre==f){if(x->pre->ch[0]==x){Rotate(x,1);}else{Rotate(x,0);}}else{Node *y=x->pre,*z=y->pre;if(z->ch[0]==y){if(y->ch[0]==x){Rotate(y,1);Rotate(x,1);}else{Rotate(x,0);Rotate(x,1);}}else{if(y->ch[1]==x){Rotate(y,0);Rotate(x,0);}else{Rotate(x,1);Rotate(x,0);}}}}pushup(x);}Node *kth(Node *rt,int k){if(rt->ch[0]->size+1==k)return rt;if(k<=rt->ch[0]->size)return kth(rt->ch[0],k);elsereturn kth(rt->ch[1],k-(rt->ch[0]->size)-1);}int main(){int n,m,i;Node *L,*R;while(scanf("%d%d",&n,&m)==2){for(i=1;i<=n;i++)scanf("%d",&num[i]);tot=0;num[0]=0;num[n+1]=0;root=build(1,n+2);char op[2];int x,y;while(m--){scanf("%s%d%d",op,&x,&y);if(op[0]=='Q'){y+=2;L=kth(root,x);R=kth(root,y);splay(L,null);splay(R,L);printf("%d\n",R->ch[0]->mx);root=L;}else{x++;L=kth(root,x);splay(L,null);root=L;root->val=y;pushup(root);}}}return 0;}


0 0
原创粉丝点击