您的位置:首页 > 理论基础 > 数据结构算法

poj 3580 SuperMemo 数据结构

2012-02-13 22:36 253 查看
题意:给一堆操作,维护数列。

思路:平衡树 splay

P.S. 太恶心了……

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 110004
#define MAXM 110000
struct node
{
int left,right,father;
int value,size,min;
int adt;
bool rev;
};
int INF=987654321;
int top=0;
int n,m;
node tree[MAXN+MAXM];
int tmp[MAXN];
int root;
void update(int x)
{
if(x!=0)
{
tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
tree[x].min=min(tree[tree[x].left].min,tree[tree[x].right].min);
tree[x].min=min(tree[x].min,tree[x].value);
}
}
void newnode(int lnum,int rnum,int value)
{
tree[++top].left=lnum; tree[top].right=rnum;
tree[top].value=value;
update(top);
tree[rnum].father=tree[lnum].father=top;
}
int build_tree(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)/2;
int lnum=build_tree(l,mid-1);
int rnum=build_tree(mid+1,r);
newnode(lnum,rnum,tmp[mid]);
return top;
}
void pushdown(int x)
{
if(x!=0&&tree[x].rev)
{
swap(tree[x].left,tree[x].right);
tree[tree[x].left].rev=!tree[tree[x].left].rev;
tree[tree[x].right].rev=!tree[tree[x].right].rev;
tree[x].rev=false;
}
if(x!=0&&tree[x].adt!=0)
{
tree[tree[x].left].adt+=tree[x].adt;
tree[tree[x].right].adt+=tree[x].adt;
if(tree[x].left!=0)
tree[tree[x].left].min+=tree[x].adt;
if(tree[x].right!=0)
tree[tree[x].right].min+=tree[x].adt;
tree[tree[x].left].value+=tree[x].adt;
tree[tree[x].right].value+=tree[x].adt;
tree[x].adt=0;
}
}

void leftrotate(int x)
{
int y=tree[x].father;
int z=tree[x].left;
if(y==tree[tree[y].father].left) tree[tree[y].father].left=x;
else tree[tree[y].father].right=x;
tree[x].father=tree[y].father;
tree[x].left=y;
tree[y].father=x;
tree[y].right=z;
tree[z].father=y;
update(y); update(x);
}
void rightrotate(int x)
{
int y=tree[x].father;
int z=tree[x].right;
if(y==tree[tree[y].father].right) tree[tree[y].father].right=x;
else tree[tree[y].father].left=x;
tree[x].father=tree[y].father;
tree[x].right=y;
tree[y].father=x;
tree[y].left=z;
tree[z].father=y;
update(y); update(x);
}
void splay(int rootnew,int x)
{
pushdown(x);
int y,z;
int i=0;
int fa=tree[rootnew].father;
while(tree[x].father!=fa)
{
y=tree[x].father;
z=tree[y].father;
if(z==fa)
{
if(tree[y].left==x) rightrotate(x);
else leftrotate(x);
break;
}
if(tree[z].left==y)
{
if(tree[y].left==x) {rightrotate(y),rightrotate(x);}
else leftrotate(x),rightrotate(x);
}
else
{
if(tree[y].left==x) rightrotate(x),leftrotate(x);
else leftrotate(y),leftrotate(x);
}
}
if(rootnew==root)
root=x;
}
void find(int root,int pos)
{
int x=root;
while(pushdown(x),tree[tree[x].left].size+1!=pos)
{
if(tree[tree[x].left].size>=pos) x=tree[x].left;
else
pos-=tree[tree[x].left].size+1, x=tree[x].right;
}
splay(root,x);
}
void add(int l,int r,int z)
{
find(root,l);
find(tree[root].right,r-l);
int p=tree[tree[root].right].left;
tree[p].adt+=z; tree[p].value+=z; tree[p].min+=z;
splay(root,p);
}
void reverse(int l,int r)
{
find(root,l);
find(tree[root].right,r-l);
int p=tree[tree[root].right].left;
tree[p].rev=!tree[p].rev;
}
void revolve(int l,int r,int a)
{
find(root,l);
find(tree[root].right,r-l);
find(tree[tree[root].right].left,tree[tree[tree[root].right].left].size-a);
find(tree[tree[tree[root].right].left].right,tree[tree[tree[tree[root].right].left].right].size);
int p=tree[tree[root].right].left;
int t=tree[tree[tree[root].right].left].right;
tree[p].right=0;
tree[tree[p].father].left=t; tree[t].father=tree[p].father;
tree[t].right=p; tree[p].father=t;
update(p);
splay(root,p);
}
void insert(int pos,int value)
{
find(root,pos);
find(tree[root].right,1);
newnode(0,0,value);
int p=tree[root].right;
tree[p].left=top;
tree[top].father=p;
splay(root,top);
}
void del(int pos)
{
find(root,pos);
find(tree[root].left,tree[tree[root].left].size);
tree[tree[root].left].right=tree[root].right;
tree[tree[root].right].father=tree[root].left;
root=tree[root].left;
tree[root].father=0;
update(root);
}
int MIN(int l,int r)
{
find(root,l); find(tree[root].right,r-l);
int p=tree[tree[root].right].left;
return tree[p].min;
}

int main()
{
scanf("%d",&n);
int i;
int x,y,z;
memset(tree,0,sizeof(tree));
tree[0].min=INF; tree[0].size=0; tmp[1]=INF;
for(i=2;i<=n+1;i++) scanf("%d",tmp+i);
tmp[n+2]=INF;
root=build_tree(1,n+2); tree[root].father=0;
scanf("%d",&m);
char c[20];
for(i=1;i<=m;i++)
{
scanf("%s",c);
if(strcmp(c,"ADD")==0)
{
scanf("%d%d%d",&x,&y,&z); add(x,y+2,z);
}
if(strcmp(c,"REVERSE")==0)
{
scanf("%d%d",&x,&y); reverse(x,y+2);
}
if(strcmp(c,"REVOLVE")==0)
{
scanf("%d%d%d",&x,&y,&z);
if(z%(y-x+1))
revolve(x,y+2,z%(y-x+1));
}
if(strcmp(c,"INSERT")==0)
{
scanf("%d%d",&x,&y);
insert(x+1,y);
}
if(strcmp(c,"DELETE")==0)
{
scanf("%d",&x); del(x+1);
}
if(strcmp(c,"MIN")==0)
{
scanf("%d%d",&x,&y); printf("%d\n",MIN(x,y+2));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: