N个灯摆成一排,每个灯有一个权值和一个状态,现在有以下操作:
Q l r sta :查询第l个到第r个中状态为sta的灯的权值的最大公约数。
I i x sta : 在第i个灯后面插入一个权值为x状态为sta的灯。
D i:删除第i个灯
M i x :将第i个灯的权值变成x
R i:改变第i个灯的状态。
对每一个查询,输出一个答案。
又是插入又是删除,而且key值又可以合并成一段处理..容易想到splay。每个节点用两个值分别记录一下不同状态的子树区间的gcd值就可以,对于不符合要求状态的灯,gcd可以直接用-1表示,在求gcd的时候特判下0,1就可以,其他的操作就是基本操作了....init写错了结果调了一晚上...太傻×了=....
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=503000;
int pre[maxn];
int ch[maxn][2],size[maxn],key[maxn];
int sta[maxn];
int w[maxn];
int ww[maxn];
int g[2][maxn];
//int g[maxn];
int n,root,tot;
int gcd(int a,int b)
{
if (a<b) swap(a,b);
if (b==-1) return a;
if (b==0) return a;
else return gcd(b,a % b);
}
struct node
{
void pushup(int r)
{
if (r==0) return;
size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
int nw1,nw0;
if (sta[r]) nw1=key[r],nw0=-1;
else nw1=-1,nw0=key[r];
// g[r]=gcd(nw,gcd(g[ch[r][0]],g[ch[r][1]]));
g[0][r]=gcd(nw0,gcd(g[0][ch[r][0]],g[0][ch[r][1]]));
g[1][r]=gcd(nw1,gcd(g[1][ch[r][0]],g[1][ch[r][1]]));
}
void rotate(int x,int kind)
{
int y=pre[x];
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if (pre[y])
{
ch[pre[y]][ch[pre[y]][1]==y]=x;
}
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
pushup(y);
pushup(x);
}
void splay(int x,int tgt)
{
while(pre[x]!=tgt)
{
int y=pre[x];
if (pre[pre[x]]==tgt)
{
rotate(x,ch[pre[x]][0]==x);
}
else
{
int kind=ch[pre[y]][0]==y;
if (ch[y][kind]==x)
{
rotate(x,kind^1);
rotate(x,kind);
}
else
{
rotate(y,kind);
rotate(x,kind);
}
}
}
pushup(x);
if (tgt==0) root=x;
}
void select(int k,int tgt)
{
int rt=root;
while(true)
{
if (k<=size[ch[rt][0]]) rt=ch[rt][0];
else if (k==size[ch[rt][0]]+1) break;
else k-=(size[ch[rt][0]]+1),rt=ch[rt][1];
}
splay(rt,tgt);
}
void newnode(int &r,int father,int k,int k2)
{
r=++tot;
pre[r]=father;
size[r]=1;
g[0][r]=g[1][r]=-1;
g[k2][r]=k;
// g[r]=0;
key[r]=k;
sta[r]=k2;
ch[r][0]=ch[r][1]=0;
}
void build(int l,int r,int &x,int rt)
{
if (l>r) return;
int m,num,st;
m=(l+r)>>1;
num=w[m];
st=ww[m];
newnode(x,rt,num,st);
build(l,m-1,ch[x][0],x);
build(m+1,r,ch[x][1],x);
pushup(x);
pushup(rt);
}
void init()
{
memset(g,-1,sizeof g);
tot=root=0;
key[0]=-1;
sta[0]=-1;
newnode(root,0,-1,0);
newnode(ch[root][1],root,-1,0);
build(1,n,ch[ch[root][1]][0],ch[root][1]);
pushup(ch[root][1]);
pushup(root);
}
void print(int r,int k)
{
if (r==0) return;
print(ch[r][0],k);
if (sta[r]!=-1) printf("%d ",g[k][r]);
print(ch[r][1],k);
}
int query(int l,int r,int st)
{
r+=2;
select(l,0);
select(r,root);
return g[st][ch[ch[root][1]][0]];
}
void insert(int pos,int k,int st)
{
pos+=1;
select(pos,0);
select(pos+1,root);
newnode(ch[ch[root][1]][0],ch[root][1],k,st);
pushup(ch[root][1]);
pushup(root);
}
void del(int pos)
{
pos+=1;
select(pos-1,0);
select(pos+1,root);
ch[ch[root][1]][0]=0;
pushup(ch[root][1]);
pushup(root);
}
void modify(int pos,int k)
{
pos+=1;
select(pos,0);
key[root]=k;
pushup(root);
}
void re(int pos)
{
pos+=1;
select(pos,0);
sta[root]^=1;
pushup(root);
}
}spt;
int main()
{
// freopen("in.txt","r",stdin);
int m;
while(~scanf("%d%d",&n,&m))
{
for (int i=1; i<=n; i++)
scanf("%d%d",&w[i],&ww[i]);
spt.init();
// spt.print(root,0);
// puts("");
// spt.print(root,1);
// puts("");
char tp[10];
while(m--)
{
scanf("%s",tp);
int x,y,z;
if (tp[0]=='Q')
{
scanf("%d%d%d",&x,&y,&z);
int ans=spt.query(x,y,z);
// if (!ans) ans=-1;
printf("%d\n",ans);
}
else
if (tp[0]=='I')
{
scanf("%d%d%d",&x,&y,&z);
spt.insert(x,y,z);
}
else
if (tp[0]=='D')
{
scanf("%d",&x);
spt.del(x);
}
else
if (tp[0]=='M')
{
scanf("%d%d",&x,&y);
spt.modify(x,y);
}
else
if (tp[0]=='R')
{
scanf("%d",&x);
spt.re(x);
}
}
}
return 0;
}