一开始感觉是分块,但是好像不太兹瓷。于是觉得是莫队。
但是他有强制在线,,而且莫队还是N^1.5logN的,感觉很不兹瓷。
后来发现是假的在线。。。并且找到了一个题解发现就是N^1.5logN的,然后就做完了。
yy了一个做法就是每16个分成一块,然后O(16)修改,O(N/16)询问,配合莫队就是O(16N^1.5+N^2/16),不知道能不能过(当然不是16应该也是兹瓷的)。
AC代码如下:
#include<bits/stdc++.h>
#define ll long long
#define N 200005
using namespace std;
int n,m,rt,pt,key,blk,dfsclk,cnt,fst[N],nxt[N],a[N],q[N],rk[N];
int d[N],fa[N],son[N],sz[N],anc[N],lf[N],rg[N],id[N];
ll res,c[N],ans[N]; bool vis[N];
struct node{ int x,y,k; }b[N];
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
int lca(int x,int y){
for (; anc[x]!=anc[y]; x=fa[anc[x]])
if (d[anc[x]]<d[anc[y]]) swap(x,y);
return (d[x]<d[y])?x:y;
}
void ins(int x,int y){
if (lf[x]>lf[y]) swap(x,y);
cnt++; b[cnt]=(node){(lca(x,y)==x)?lf[x]:rg[x],lf[y],cnt+1};
}
void add(int x,ll y){
for (; x<=n; x+=x&-x) c[x]+=y;
}
ll getsum(int x){
ll y=0; for (; x; x^=x&-x) y+=c[x]; return y;
}
void mdy(int y){
int x=rk[y]; vis[y]^=1;
if (vis[y]){
pt++; add(x,(ll)a[y]*n+1);
ll z=getsum(x)-1; res+=(ll)a[y]*(pt-z%n-1)+z/n;
} else{
ll z=getsum(x)-1; res-=a[y]*(pt-z%n-1)+z/n;
pt--; add(x,-((ll)a[y]*n+1));
}
}
void dfs(int x){
int y; sz[x]=1;
for (y=fst[x]; y; y=nxt[y]){
d[y]=d[x]+1;
dfs(y); sz[x]+=sz[y];
if (sz[y]>sz[son[x]]) son[x]=y;
}
}
void dvd(int x,int tp){
int y; anc[x]=tp;
lf[x]=++dfsclk; id[dfsclk]=x;
if (son[x]) dvd(son[x],tp);
for (y=fst[x]; y; y=nxt[y])
if (y!=son[x]) dvd(y,y);
rg[x]=++dfsclk; id[dfsclk]=x;
}
bool cmp1(int x,int y){ return a[x]<a[y]; }
bool cmp2(node u,node v){ return (u.x/blk==v.x/blk)?u.y<v.y:u.x<v.x; }
int main(){
n=read(); m=read(); key=read();
blk=(int)sqrt(2*n);
int i,x,y,z; char ch[10];
for (i=1; i<=n; i++){ a[i]=read(); q[i]=i; }
sort(q+1,q+n+1,cmp1);
for (i=1; i<=n; i++) rk[q[i]]=i;
for (i=1; i<=n; i++){
scanf("%d",&x);
if (x){
fa[i]=x; nxt[i]=fst[x]; fst[x]=i;
} else rt=i;
}
d[rt]=1; dfs(rt); dvd(rt,rt);
for (i=x=1; i<=m; i++){
scanf("%s",ch); y=read();
if (ch[0]=='C') x=y; else{
ins(x,y%n+1); ins(x,(y+key)%n+1);
}
}
sort(b+1,b+cnt+1,cmp2);
int l=1,r=0;
for (i=1; i<=cnt; i++){
while (b[i].x<l) mdy(id[--l]); while (b[i].y>r) mdy(id[++r]);
while (b[i].x>l) mdy(id[l++]); while (b[i].y<r) mdy(id[r--]);
x=id[l]; y=id[r]; z=lca(x,y);
if (x!=z) mdy(z); ans[b[i].k]=res; if (x!=z) mdy(z);
}
ll tmp=0;
for (i=1; i<=(cnt>>1); i++){
tmp=ans[i<<1|(tmp&1)];
printf("%lld\n",tmp);
}
return 0;
}
by lych
2017.2.19