poj 3580 splay tree

splay tree 的孩子父亲关系 既可以是 大小的偏序关系 ,也可以是位置的偏序关系~~~

这道题用的是位置的偏序关系~~~

#include <stdio.h>   
#include <iostream>
#include <string.h>   
#include <cmath>
#include <algorithm>   
#define fr(i,s,n) for(int i=s;i<n;++i)
#define _fr(i,n,s) for(int i=n-1;i>=s;--i)
#define fi freopen("in.txt","r",stdin)
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int N=100010;
const int INF = 0x7fffffff;
class Spt{
	public:
		int t;
		struct Spt_node{
			int val,siz,laz,mn;//sum
			bool is_rev;
			Spt_node *pa,*lc,*rc;
		}  node[N<<1] , *root,*nil;

	public:
		Spt(){
			nil = new Spt_node();
			nil->siz = t =0;
			nil->val  = nil->mn = INF;
			nil->lc = nil->rc = nil->pa = nil;
		}
		/****************************************************/
		inline Spt_node * new_node(Spt_node *pa,const int val){
			node[t].mn = node[t].val = val;
			node[t].siz = 1;
			node[t].laz = 0;
			node[t].pa = pa;
			node[t].lc = node[t].rc = nil;
			node[t].is_rev = 0;
			return &node[t++];
		}
		Spt_node * build(int l , int r , Spt_node *pa , int arr[]){
			if (l > r) return nil;
			int m = (l+r) >> 1;
			Spt_node * x = new_node(pa , arr[m]);
			x->lc = build(l,m-1,x,arr);
			x->rc = build(m + 1,r ,x,arr);
			up(x);
			return x;
		}
		inline void zig(Spt_node *pos){
			Spt_node *p = pos->pa;
			down(p->rc);down(pos->lc);down(pos->rc);
			p->lc = pos->rc; p->lc->pa = p;
			pos->rc = p; pos->pa = p->pa;
			if (p->pa->lc == p) p->pa->lc = pos;
			else p->pa->rc = pos;
			p->pa = pos;
			up(p); up(pos);
			if(root == p) root = pos;
		}
		inline void zag(Spt_node *pos){
			Spt_node *p = pos->pa;
			down(p->lc);down(pos->lc);down(pos->rc);
			p->rc = pos->lc; p->rc->pa = p;
			pos->lc = p; pos->pa = p->pa;
			if (p->pa->lc == p) p->pa->lc = pos;
			else p->pa->rc = pos;
			p->pa = pos;
			up(p); up(pos);
			if(root == p) root = pos;
		}
		inline void splay(Spt_node *pos , Spt_node *root){  //这里的root是指要旋转到的根 
			down( pos);

			while(pos->pa != root){
				if (pos->pa->pa == root) {
					if (pos->pa->lc == pos) zig(pos);
					else zag(pos);
				}else if (pos->pa->pa->lc == pos->pa){
					if (pos->pa->lc == pos) zig(pos->pa),zig(pos);
					else zag(pos),zig(pos);
				}else{
					if (pos->pa->lc == pos) zig(pos),zag(pos);
					else zag(pos->pa),zag(pos);
				}
			}
		}
		inline void find(int k,Spt_node *pos){  //将k处的节点旋转到pos
			Spt_node * p = root;
			down(p);
			while(k != p->lc->siz + 1){
				if (k <= p->lc->siz) p = p->lc;
				else k -= p->lc->siz +1 ,p = p->rc;
				down(p);
			}
			splay(p,pos);
		}
		/************/
		inline void up(Spt_node * pos){
			if (pos == nil) return;
			pos->siz = pos->lc->siz + pos->rc->siz + 1;
			pos->mn = min(pos->val,min(pos->lc->mn,pos->rc->mn));
		}
		inline void down(Spt_node * pos){
			if (pos == nil) return;
			if (pos->is_rev){
				swap(pos->lc,pos->rc);
				pos->lc->is_rev ^= true;
				pos->rc->is_rev ^= true;
				pos->is_rev = 0;
			}
			if (pos->laz){
				pos->val += pos->laz;
				pos->mn += pos->laz;
				pos->lc->laz += pos->laz;
				pos->rc->laz += pos->laz;
				pos->laz = 0;
			}
		}
		/***********/
		void build(int arr[],int n){ 
			int m = (n >> 1);
			root = new_node( nil, arr[m]);
			root->lc = build(0,m-1,root,arr);
			root->rc = build(m+1, n, root ,arr);
			up(root);
		}
		inline void add(int l,int r,int d){
			find(l,nil);//因为多加了两个收尾节点所以这里的find 是旋转l前一个
			
			find(r+2,root);
			
			root->rc->lc->laz += d;
		}
		inline void ins(int pos,int d){
			find(pos+1,nil);
			find(pos+2,root);
			root->rc->lc = new_node(root->rc,d);
		}
		inline void del(int pos){
			find(pos,nil);
			find(pos+2,root);
			root->rc->lc = nil;
		}
		inline int getmn(int l,int r){
			find(l,nil);
			find(r+2,root);
			down(root->rc->lc);
			return root->rc->lc->mn;
		}
		inline void reverse(int l,int r){
			find(l,nil);
			find(r+2,root);
			root->rc->lc->is_rev ^= true;
		}
		inline void revolve(int l,int r,int T){
			int len = r - l + 1;
			T = ((T % len) + len) % len;
			if (T){
				find(r - T + 1,nil);
				find(r + 2,root);
				Spt_node *tmp = root->rc->lc;
				root->rc->lc = nil;
				find(l,nil);
				find(l+1,root);
				root->rc->lc = tmp;
				tmp->pa = root->rc;
			}
		}
		/****************/
		void disp(const Spt_node * root){
			if (root->lc != nil){
				cout<<root->val<<"的左孩子是:"<<root->lc->val<<"min是"<<root->lc->siz<<endl;
				disp(root->lc);
			}
			if (root ->rc != nil){
				cout<<root->val<<"的右孩子是:"<<root->rc->val<<"min是"<<root->rc->siz<<endl;
				disp(root->rc);
			}
		}	
}spt;


int arr[N];
int main(){
	int n,m; char op[20];
	scanf("%d", &n);
	fr(i,1,n+1) scanf("%d",&arr[i]);
	arr[0] = arr[n+1] = INF;
	spt.build(arr , n+1);
	scanf("%d",&m);
	int l,r,d,T;
	fr(i,0,m){
		scanf("%s",op);
		switch(op[0]){
		case  'A' :
			scanf("%d%d%d",&l,&r,&d);
			spt.add(l,r,d);
			break;
		case 'R' :
			if('E' == op[3]){
				scanf("%d%d", &l, &r);
				spt.reverse(l, r);
			}else{
				scanf("%d%d%d", &l, &r,&T);
				spt.revolve(l,r,T);
			}
			break;	
		case 'I' :
			scanf("%d%d", &l, &d);
			spt.ins(l,d);
			break;
		case 'D' :
			scanf("%d", &l);
			spt.del(l);	
			break;
		case 'M' :
			scanf("%d%d", &l, &r);
			printf("%d\n",spt.getmn(l,r));
		}
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值