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;
}