您的位置:首页 > 其它

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

2013-01-29 14:57 477 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: