此题最好用BIT,线段树TLE了..
我们先构建点分树, nlog2n n l o g 2 n 把每个重心所管辖子树内每个点以距离为下标,点权为值加入到动态开点线段树里,注意这里要分别建两棵线段树,一棵处理重心,一棵处理重心到点分树上的父节点处理的容斥信息。
修改和求和都可以 nlog2n n l o g 2 n 处理。
这题最坑的是:暴力跳点分树的时候不会中途弹出,有可能其中有一层的父节点离x很远,下一个又很近。要是中途弹出会RE(WA)到死TAT
还有就是空间往大了开…
#include
using namespace std;
const int N=500100;
const int M=N<<4;
int n,m,val[N],f[N],vis[N],d[N];
int F[N][23],D[N],bin[23];
int S,MX,sz[N],mx[N],root,ans;
int head[N],to[N<<1],nxt[N<<1],tot;
int ss[M],cnt;
int rt[N][2],ls[M],rs[M];
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
inline void dfs(int x)
{
int i,j;
for(i=1;bin[i]<=D[x];++i)
F[x][i]=F[F[x][i-1]][i-1];
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==F[x][0]) continue;
F[j][0]=x;D[j]=D[x]+1;
dfs(j);
}
}
inline int LCA(int x,int y)
{
if(D[x]int i,j,t=D[x]-D[y];
for(i=0;bin[i]<=t;++i)
if(bin[i]&t) x=F[x][i];
if(x==y) return x;
for(i=18;i>=0 && x!=y;--i)
if(F[x][i]!=F[y][i])
x=F[x][i],y=F[y][i];
return x==y?x:F[x][0];
}
inline int getdis(int x,int y)
{return D[x]+D[y]-2*D[LCA(x,y)];}
inline void getrt(int x,int fa)
{
int i,j;
sz[x]=1;mx[x]=0;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(vis[j] || j==fa) continue;
getrt(j,x);sz[x]+=sz[j];
mx[x]=max(mx[x],sz[j]);
}
mx[x]=max(mx[x],S-sz[x]);
if(mx[x]inline void getsz(int x,int fa)
{
sz[x]=1;
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(vis[j] || j==fa) continue;
getsz(j,x);sz[x]+=sz[j];
}
}
inline void ad(int &k,int l,int r,int pos,int vv)
{
if(!k) {cnt++;k=cnt;}
ss[k]+=vv;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) ad(ls[k],l,mid,pos,vv);
else ad(rs[k],mid+1,r,pos,vv);
}
inline int get(int k,int l,int r,int pos)
{
if(!k) return 0;
if(r<=pos) return ss[k];
int re=0,mid=(l+r)>>1;
re+=get(ls[k],l,mid,pos);
if(pos>mid) re+=get(rs[k],mid+1,r,pos);
return re;
}
inline void update(int u,int l,int x,int fa)
{
ad(rt[u][l],0,n,d[x],val[x]);
for(int j,i=head[x];i;i=nxt[i]){
j=to[i];if(vis[j] || j==fa) continue;
d[j]=d[x]+1;update(u,l,j,x);
}
}
inline void build(int x)
{
int i,j;
vis[x]=1;d[x]=0;update(x,0,x,0);
for(i=head[x];i;i=nxt[i]){
j=to[i];if(vis[j]) continue;
getsz(j,x);S=sz[j];MX=n+1;
getrt(j,x);f[root]=x;
d[j]=1;update(root,1,j,x);
build(root);
}
}
int main(){
int i,j,op,ix,iy,dd;
bin[0]=1;for(i=1;i<21;++i) bin[i]=bin[i-1]<<1;
n=rd();m=rd();
for(i=1;i<=n;++i) val[i]=rd();
for(i=1;i1);
S=n;MX=n+1;getrt(1,0);
build(root);
while(m--){
op=rd();
ix=rd()^ans;iy=rd()^ans;
if(!op){
ans=0;dd=0;
for(i=ix;i;i=f[i]){
if(iy>=dd) ans+=get(rt[i][0],0,n,iy-dd);
if(!f[i]) break;
dd=getdis(f[i],ix);
if(iy>=dd) ans-=get(rt[i][1],0,n,iy-dd);
}
printf("%d\n",ans);
}else{
j=iy-val[ix];dd=0;
for(i=ix;i;i=f[i]){
ad(rt[i][0],0,n,dd,j);
if(!f[i]) break;
dd=getdis(f[i],ix);
ad(rt[i][1],0,n,dd,j);
}
val[ix]=iy;
}
}
}