poj 3580 Splay Tree 各种基本操作与实现

POJ 3580 ,这道题需要的操作包括:

  1.区间增加相同的数

  2.区间反转

  3.区间滚动

  4.插入一个数

  5.删除一个数

  6.查询一个区间内的最小值

/*
POJ 3580 ,这道题需要的操作包括:

  1.区间增加相同的数

  2.区间反转

  3.区间滚动

  4.插入一个数

  5.删除一个数

  6.查询一个区间内的最小值
*/
#include <cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#define keyTree (ch[ ch[root][1] ][0])
const int maxn = 2222222;
const int inf=1<<30;
struct SplayTree{
	int sz[maxn];
	int ch[maxn][2];
	int pre[maxn];
	int root , top1 , top2;
	int ss[maxn] ,que[maxn];
	inline void Rotate(int x,int f) {
		int y = pre[x];
		push_down(y);
		push_down(x);
		ch[y][!f] = ch[x][f];
		pre[ ch[x][f] ] = y;
		pre[x] = pre[y];
		if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
		ch[x][f] = y;
		pre[y] = x;
		push_up(y);
	}
	inline void Splay(int x,int goal) {
		push_down(x);
		while(pre[x] != goal) {
			if(pre[pre[x]] == goal) {
				Rotate(x , ch[pre[x]][0] == x);
			} else {
				int y = pre[x] , z = pre[y];
				int f = (ch[z][0] == y);
				if(ch[y][f] == x) {
					Rotate(x , !f) , Rotate(x , f);
				} else {
					Rotate(y , f) , Rotate(x , f);
				}
			}
		}
		if(goal == 0) root = x;	push_up(x);
	}
	inline void RotateTo(int k,int goal) {///把第k位的数转到goal下边
		int x = root;
		push_down(x);
		while(sz[ ch[x][0] ] != k){
			if(k < sz[ ch[x][0] ]) {
				x = ch[x][0];
			} else {
				k -= (sz[ ch[x][0] ] + 1);
				x = ch[x][1];
			}
			push_down(x);
		}
		Splay(x,goal);
	}
	inline void erase(int x){///把以x为祖先结点删掉放进内存池,回收内存
		int father = pre[x];
		int head = 0 , tail = 0;
		//push_down(x);
		for (que[tail++] = x ; head < tail ; head ++) {
			ss[top2 ++] = que[head];
			if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];
			if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];
		}
		ch[ father ][ ch[father][1] == x ] = 0;
		//push_up(father);
	}
	///找前驱,即左子树的最右结点
    int get_pre(int x){
	   int tmp=ch[x][0];
	   if(tmp==0)  return inf;
	   while(ch[tmp][1])
		 tmp=ch[tmp][1];
	  return val[tmp];
    }
    ///找后继,即右子树的最左结点
    int get_next(int x){
	int tmp=ch[x][1];
	if(tmp==0)  return inf;
	while(ch[tmp][0])
		tmp=ch[tmp][0];
	return val[tmp];
    }
	///以上一般不修改//////////////////////////////////////////////////////////////////////////////
	void debug() {printf("%d\n",root);Treaval(root);}
	void Treaval(int x) {
		if(x) {
			Treaval(ch[x][0]);
			printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
			Treaval(ch[x][1]);
		}
	}
	///以上Debug
	///以下是题目的特定函数:
	inline void NewNode(int &x,int c,int fa) {
		if (top2) x = ss[--top2];///用栈手动压的内存池
		else
		x = ++top1;
		ch[x][0] = ch[x][1] = 0;
		pre[x]=fa;
		sz[x] = 1;
		val[x] =mi[x]=c;///*这是题目特定函数*/
		add[x] = rev[x]=0;
	}
	inline void Rev(int x){
	    if(!x)return;
	    swap(ch[x][0],ch[x][1]);
	    rev[x]^=1;
	}
	void Add(int x,int v)
    {
      if(!x) return;
       val[x]+=v;
      mi[x]+=v;
      add[x]+=v;
    }
	///把延迟标记推到孩子
	inline void push_down(int x) {///*这是题目特定函数*/
		if(add[x]){
			  Add(ch[x][0],add[x]),Add(ch[x][1],add[x]);
		    }
		if(rev[x]){
		   Rev(ch[x][0]);
		   Rev(ch[x][1]);
		}
        add[x] = rev[x]=0;
	}
	///把孩子状态更新上来
	inline void push_up(int x) {
		sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
		///*这是题目特定函数*/
		mi[x]=min(val[x],min(mi[ch[x][0]],mi[ch[x][1]]));
	}
	///*初始化*/
	inline void makeTree(int &x,int l,int r,int f) {
		if(l > r) return ;
		int m = (l + r)>>1;
		NewNode(x , num[m],f);		///*num[m]权值改成题目所需的*/
		makeTree(ch[x][0] , l , m - 1 , x);
		makeTree(ch[x][1] , m + 1 , r , x);
		pre[x] = f;
		push_up(x);
	}
	inline void init(int n) {///*这是题目特定函数*/
		ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
		add[0] = rev[0]=top2=top1 = 0;
		///为了方便处理边界,加两个边界顶点
        val[0]=mi[0]=inf;
        NewNode(root,-inf,0);
        NewNode(ch[root][1],inf,root);
	//	pre[top1] = 0;
		sz[root] = 2;
		for (int i = 1 ;i <=n ; i ++) scanf("%d",&num[i]);
		makeTree(keyTree , 1 , n , ch[root][1]);
		push_up(ch[root][1]);
		push_up(root);
	}
	///*add 更新*/
	inline void update(int l,int r,int c) {///*这是题目特定函数*/
		RotateTo(l-1,0);
		RotateTo(r+1,root);
		add[ keyTree ] += c;
		mi[keyTree]+=c;
		val[keyTree]+=c;
	}
	///删除
	inline void del(int pos)
   {
     RotateTo(pos-1,0);
     RotateTo(pos+1,root);
     keyTree=0;
     push_up(ch[root][1]);
     push_up(root);
   }
	///滚动
	inline void revolve(int l,int r,int num)
   {
    num%=(r-l+1);
    num=(num+(r-l+1))%(r-l+1);
    if(!num) return;
    RotateTo(r-num,0);
    RotateTo(r+1,root);
    int x=keyTree;
    keyTree=0;
    push_up(ch[root][1]);
    push_up(root);
    RotateTo(l-1,0);
    RotateTo(l,root);
    keyTree=x;
    pre[keyTree]=ch[root][1];
    push_up(ch[root][1]);
    push_up(root);
    }
	///插入
	inline void insert(int pos,int num)
    {
    RotateTo(pos,0);
    RotateTo(pos+1,root);
    NewNode(keyTree,num,ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
    }
    ///翻转
    inline void revese(int l,int r)
    {
      RotateTo(l-1 , 0);
      RotateTo(r+1 , root);
      Rev(keyTree);
    }
	///*询问*/
	inline void getmin(int l,int r)
    {
      RotateTo(l-1 , 0);
      RotateTo(r+1 , root);
      printf("%d\n",mi[keyTree]);
    }
	///*这是题目特定变量*/
	int num[maxn];
	int val[maxn];
	int add[maxn];
	int mi[maxn] ;
	int rev[maxn];
}spt;
int main()
{
    char op[10];
    int l,r,c,pos,num,i,n,m;
//  freopen("//media/学习/ACM/input.txt","r",stdin);
    while(scanf("%d",&n)!=EOF){
       spt.init(n);
        scanf("%d",&m);
        while(m--){
            scanf("%s",op);
            if(op[0]=='I'){
                scanf("%d%d",&pos,&num);
                spt.insert(pos,num);
            }
            else if(op[0]=='D'){
                scanf("%d",&pos);
                spt.del(pos);
            }
            else if(op[0]=='A'){
                scanf("%d%d%d",&l,&r,&c);
                if(l>r) swap(l,r);
                spt.update(l,r,c);
               // spt.debug();
            }
            else if(op[0]=='R'&&op[3]=='E'){
                scanf("%d%d",&l,&r);
                if(l>r) swap(l,r);
                spt.revese(l,r);
            }
            else if(op[0]=='M'){
                scanf("%d%d",&l,&r);
                if(l>r) swap(l,r);
                spt.getmin(l,r);
            }
            else{
                scanf("%d%d%d",&l,&r,&c);
                if(l>r) swap(l,r);
                spt.revolve(l,r,c);
            }
        }
    }
    return 0;
}




你可能感兴趣的:(poj 3580 Splay Tree 各种基本操作与实现)