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; }