您的位置:首页 > 其它

ZOJ 3765 Lights Splay Tree的几种基本操作

2014-05-27 19:51 489 查看
区间的查询,点修改,插入和删除。先姑且当作模板吧,略挫,慢慢补充,慢慢优化。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 9999991

using namespace std;

const int MAXN = 700100;

struct N
{
//info
int son[2],pre;

//data
int sta,ls,rs,s;
int w,g[2];
bool mark[2];

}st[MAXN];

struct W
{
int sta,w;
}num[200100];

void Output(int root)
{
if(root == -1)
return ;
Output(st[root].son[0]);
printf("root = %d pre = %d data = %2d lg = %2d rg = %2d sta = %2d ls = %d rs = %d s = %d\n",root,st[root].pre,st[root].w,st[root].g[0],st[root].g[1],st[root].sta,st[root].ls,st[root].rs,st[root].s);
Output(st[root].son[1]);
}

int Top;

int Gcd(int a,int b)
{
int t;

while(b)
{
t = a;
a = b;
b = t%b;
}
return a;
}

//更新st[root]的数据域
void Updata(int root)
{
st[root].ls = 0,st[root].rs = 0;

st[root].g[st[root].sta] = st[root].w;
st[root].g[1^st[root].sta] = 1;
st[root].mark[st[root].sta] = true;
st[root].mark[1^st[root].sta] = false;

if(st[root].son[0] != -1)
{
if(st[root].mark[0] == true)
st[root].g[0] = (st[st[root].son[0]].mark[0] ? Gcd(st[root].g[0],st[st[root].son[0]].g[0]) : st[root].g[0]);
else
st[root].g[0] = st[st[root].son[0]].g[0];
if(st[root].mark[1] == true)
st[root].g[1] = (st[st[root].son[0]].mark[1] ? Gcd(st[root].g[1],st[st[root].son[0]].g[1]) : st[root].g[1]);
else
st[root].g[1] = st[st[root].son[0]].g[1];

st[root].mark[0] = (st[root].mark[0] || st[st[root].son[0]].mark[0]);
st[root].mark[1] = (st[root].mark[1] || st[st[root].son[0]].mark[1]);
st[root].ls = st[st[root].son[0]].s;
}

if(st[root].son[1] != -1)
{
if(st[root].mark[0] == true)
st[root].g[0] = (st[st[root].son[1]].mark[0] ? Gcd(st[root].g[0],st[st[root].son[1]].g[0]) : st[root].g[0]);
else
st[root].g[0] = st[st[root].son[1]].g[0];
if(st[root].mark[1] == true)
st[root].g[1] = (st[st[root].son[1]].mark[1] ? Gcd(st[root].g[1],st[st[root].son[1]].g[1]) : st[root].g[1]);
else
st[root].g[1] = st[st[root].son[1]].g[1];

st[root].mark[0] = (st[root].mark[0] || st[st[root].son[1]].mark[0]);
st[root].mark[1] = (st[root].mark[1] || st[st[root].son[1]].mark[1]);
st[root].rs = st[st[root].son[1]].s;
}

st[root].s = st[root].ls + st[root].rs + 1;
}

void Init(int &root,int s,int e,int pre)
{
if(s > e)
return ;

int mid = (s+e)>>1;

root = Top++;
st[root].w = num[mid].w;
st[root].sta = num[mid].sta;

st[root].pre = pre;
st[root].son[0] = st[root].son[1] = -1;

Init(st[root].son[0],s,mid-1,root);
Init(st[root].son[1],mid+1,e,root);

Updata(root);
}

//dir == 0,root为pre的左儿子,dir == 1时为右儿子。
void Rotate(int root,int dir)
{
//旋转操作
st[st[root].pre].son[dir] = st[root].son[1^dir];
st[root].son[1^dir] = st[root].pre;

if(st[st[st[root].pre].pre].son[0] == st[root].pre)
st[st[st[root].pre].pre].son[0] = root;
else
st[st[st[root].pre].pre].son[1] = root;
int temp = st[root].pre;
st[root].pre = st[st[root].pre].pre;
st[temp].pre = root;

if(st[temp].son[dir] != -1)
st[st[temp].son[dir]].pre = temp;

//更新数据域
Updata(temp);
Updata(root);
}

//将root旋转到goal下面,goal == 0时即表示将root旋转至根节点位置。
int Splay(int root,int goal)
{
while(st[root].pre != goal)
{
Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1));
}

return root;
}

int Search_Site(int root,int site)
{
while(st[root].ls + 1 != site)
{
if(st[root].ls + 1 < site)
{
site = site - st[root].ls - 1;
root = st[root].son[1];
}
else
{
root = st[root].son[0];
}
}

return root;
}

void Increase(int root,int site,int w,int sta,int &R)
{
root = Search_Site(root,site);

R = Splay(root,0);

//在根节点的右子树的最左边插入一个点

int tr = st[R].son[1];
st[R].son[1] = -1;

int New = Top++;

st[New].w = w;
st[New].sta = sta;

st[New].pre = 0;
st[0].son[0] = New;
st[R].pre = New;
st[New].son[0] = R;
st.pre = New;
st[New].son[1] = tr;

Updata(R);
Updata(New);
R = New;
}

void Link(int &root,int tr,int pre)
{
if(root == -1)
{
root = tr;
st[root].pre = pre;
}
else
{
Link(st[root].son[1],tr,root);
}
Updata(root);
}

//不存在删除所有节点的情况
void Decrease(int root,int site,int &R)
{
root = Search_Site(root,site);
//Output(R);
// printf("D site = %d root = %d R = %d\n",site,root,R);

R = Splay(root,0);
//删除根节点

R = st[root].son[0];
st[R].pre = st[root].pre;
st[0].son[0] = R;
int tr = st[root].son[1];

//将tr接到R的最右边。

Link(R,tr,root);
Updata(R);
}

void Reinit(int root,int site,int &R)
{
root = Search_Site(root,site);

R = Splay(root,0);

st[R].sta ^= 1;
Updata(R);
}

void Modify(int root,int site,int w,int &R)
{
root = Search_Site(root,site);

R = Splay(root,0);

st[R].w = w;
Updata(R);
}

int Query(int root,int l,int r,int sta,int &R)
{
int lsite = Search_Site(root,l);
int rsite = Search_Site(root,r);

R = Splay(rsite,0);

R = Splay(lsite,0);

if(st[st[R].son[1]].son[0] == -1 || st[st[st[R].son[1]].son[0]].mark[sta] == false)
return -1;
return st[st[st[R].son[1]].son[0]].g[sta];
}

int main()
{
//freopen("data.txt","r",stdin);
//freopen("dataout.txt","w",stdout);
int n,m;

int i;

int root;

while(scanf("%d %d",&n,&m) != EOF)
{
for(i = 2;i <= n+1; ++i)
{
scanf("%d %d",&num[i].w,&num[i].sta);
}

// cout<<n<<" "<<m<<endl;

num[1].w = 1,num[1].sta = 0;
num[n+2].w = 1,num[n+2].sta = 0;

//Top从1开始是为了将st[0]拿出来做
//根节点的虚拟父节点,在缩短代码的同时防止RE。
Top = 1,root = -1;

Init(root,1,n+2,0);
// cout<<"dfadsf"<<endl;
st[0].son[0] = root,st[0].son[1] = -1;

char order[2];

int site,sta,l,r,w;

for(i = 1;i <= m; ++i)
{
scanf("%s",order);

if(order[0] == 'I')
{
scanf("%d %d %d",&site,&w,&sta);
// printf("i = %d site = %d\n",i+200000+1,site);
Increase(root,site+1,w,sta,root);
}
else if(order[0] == 'D')
{
scanf("%d",&site);
// printf("i = %d site = %d\n",i+200000+1,site);
Decrease(root,site+1,root);
}
else if(order[0] == 'R')
{
scanf("%d",&site);
Reinit(root,site+1,root);
}
else if(order[0] == 'M')
{
scanf("%d %d",&site,&w);
Modify(root,site+1,w,root);
}
else if(order[0] == 'Q')
{
scanf("%d %d %d",&l,&r,&sta);
printf("%d\n",Query(root,l,r+2,sta,root));
}
//cout<<"ans = "<<st[root].s<<endl;
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: