zoj 3765

时间:2025-02-09 17:34:02

一道区间更新、查询的题;

但是线段树不能做插入;

后来才知道用splay;

splay用来做区间查询的话,先将l-1旋转到根节点,然后把r+1旋转到根节点的右节点;

这样的话,根节点的右节点的左子树就是我们要的区间;

我的代码是网上大神的代码改了一下过来的,存着做模板;

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2000009
#define lch(rt) son[rt][0]
#define rch(rt) son[rt][1]
using namespace std; int son[maxn][],fa[maxn],size[maxn],val[maxn],st[maxn];
int gcd[maxn][],root,cnt;
int num[maxn*],fst[maxn*]; int get_gcd(int a,int b)
{
if(a==-)return b;
if(b==-)return a;
int c;
while(b)
{
c=a%b;
a=b;
b=c;
}
return a;
} void newnode(int &rt,int father,int v,int state)
{
rt=++cnt;
son[rt][]=son[rt][]=;
size[rt]=;
val[rt]=v;
fa[rt]=father;
gcd[rt][state]=v,gcd[rt][state^]=-;//attention;
st[rt]=state;
} void maintain(int rt)
{
size[rt]=size[son[rt][]]+size[son[rt][]]+;
gcd[rt][]=get_gcd(gcd[lch(rt)][],gcd[rch(rt)][]);
gcd[rt][]=get_gcd(gcd[lch(rt)][],gcd[rch(rt)][]);
gcd[rt][st[rt]]=get_gcd(gcd[rt][st[rt]],val[rt]);
} void rotate(int x,int kind)
{
int y=fa[x];
son[y][kind^]=son[x][kind];
fa[son[x][kind]]=y;
if(fa[y])
son[fa[y]][son[fa[y]][]==y]=x;
fa[x]=fa[y];
son[x][kind]=y;
fa[y]=x;
maintain(y);
} void splay(int rt,int goal)
{
while(fa[rt]!=goal)
{
int y=fa[rt];
if(fa[y]==goal)
rotate(rt,son[y][]==rt);
else
{
int kind=son[fa[y]][]==y;
if(son[y][kind]==rt)
{
rotate(rt,kind^);
rotate(rt,kind);
}
else
{
rotate(y,kind);
rotate(rt,kind);
}
}
}
maintain(rt);
if(goal==) root=rt;
} void rotateto(int k,int goal)//把第k个点旋转到目标位置;
{
int rt=root;
while(size[lch(rt)]!=k)
{
if(size[lch(rt)]>k)
rt=lch(rt);
else
{
k-=(size[lch(rt)]+);
rt=rch(rt);
}
}
splay(rt,goal);
} void build(int l,int r,int &rt,int father)
{
if(l>r) return ;
int m=(l+r)>>;
newnode(rt,father,num[m],fst[m]);
build(l,m-,lch(rt),rt);
build(m+,r,rch(rt),rt);
maintain(rt);
} int query(int L,int R,int state)
{
rotateto(L-,);
rotateto(R+,root);
return gcd[lch(rch(root))][state];
} void insert(int pos,int v,int state)//前端插入
{
rotateto(pos,);
if(lch(root)==)
{
newnode(lch(root),root,v,state);
maintain(root);
return ;
}
int rc=lch(root);
while(rch(rc))
rc=rch(rc);
splay(rc,root);
newnode(rch(rc),rc,v,state);
maintain(rc);
maintain(root);
} void del(int pos)
{
rotateto(pos,);
if(lch(root)==)
{
root=rch(root);
fa[root]=;
return ;
}
int rc=lch(root);
while(rch(rc)) rc=rch(rc);
splay(rc,root);
int rt=rch(root);
rch(rc)=rt;
fa[rt]=rc;
root=rc;
fa[rc]=;
maintain(root);
} void changes(int pos)
{
rotateto(pos,);
st[root]^=;
maintain(root);
} void modify(int pos,int v)
{
rotateto(pos,);
val[root]=v;
maintain(root);
} void init(int n)
{
for(int i=;i<n;++i)
scanf("%d%d",&num[i],&fst[i]);
lch()=rch()=;
fa[]=size[]=;val[]=-;
gcd[][]=gcd[][]=-;
cnt=;
newnode(root,,-,);
newnode(rch(root),root,-,);
build(,n-,lch(rch(root)),rch(root));
maintain(rch(root));
maintain(root);
} char s[];
int l,r,pos,state,v; int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
init(n);
while(m--)
{
scanf("%s",s);
if(s[]=='Q')
{
scanf("%d%d%d",&l,&r,&state);
int ans=query(l,r,state);
printf("%d\n",ans);
}
else if(s[]=='I')
{
scanf("%d%d%d",&pos,&v,&state);
insert(pos+,v,state);
}
else if(s[]=='D')
{
scanf("%d",&pos);
del(pos);
}
else if(s[]=='R')
{
scanf("%d",&pos);
changes(pos);
}
else
{
scanf("%d%d",&pos,&v);
modify(pos,v);
}
}
}
return ;
}