#include #include using namespace std; const int maxn=110000; int cnt,n,q,tot,pl; int Pool[maxn*50]; int head[maxn],F[maxn],dis[20][maxn],cur[maxn],id[maxn],w[maxn];//id[]为节点序列 int root,S,size[maxn],f[maxn];//f[]为删除u后,最大子树的大小 bool vis[maxn]; int ans; struct edge { int to,next; }edge[maxn<<1]; struct BIT//树状数组 { int *C,n; void init(int T)//初始化 { n=T; C=Pool+pl; pl+=n+1; for(int i=0;i<=n;i++) C[i]=0; } int que(int x)//查询前缀和 { x++; int res=0; for(int i=x;i;i-=(i&-i)) res+=C[i]; return res; } void add(int x,int y)//点更新 { x++; for(int i=x;i<=n;i+=(i&-i)) C[i]+=y; } }C[4*maxn][2];//两个树状数组 void init() { tot=cnt=pl=root=0; for(int i=1;i<=n;i++) vis[i]=head[i]=0; f[0]=S=n; } void add(int u,int v) { edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; } void getroot(int u,int fa)//获取重心 { size[u]=1; f[u]=0;//删除u后,最大子树的大小 for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v!=fa&&!vis[v]) { getroot(v,u); size[u]+=size[v]; f[u]=max(f[u],size[v]); } } f[u]=max(f[u],S-size[u]);//S为当前子树总结点数 if(f[u]1) C[idx][1].add(dis[dep-1][u],w[u]); for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v!=fa&&!vis[v]) dfs(dep,idx,v,d+1,u); } } void solve(int u,int fa) { vis[u]=1; F[id[u]=++tot]=id[fa]; cur[id[u]]=cur[id[fa]]+1; C[tot][0].init(S+1); C[tot][1].init(S+1); dfs(cur[id[u]],id[u],u,0,0); int tmp=S; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(vis[v]) continue; root=0; S=size[u]>size[v]?size[v]:tmp-size[u]; getroot(v,u); solve(root,u); } } void query(int k,int x,int y)//查询答案 { int d=max(-1,min(C[k][0].n-1,y-dis[cur[k]][x])); ans+=C[k][0].que(d); if(F[k]) { d=max(-1,min(C[k][1].n-1,y-dis[cur[k]-1][x])); ans-=C[k][1].que(d);//减去重复 query(F[k],x,y); } } void update(int k,int x,int y) //点更新 { C[k][0].add(dis[cur[k]][x],y); if(F[k]) { C[k][1].add(dis[cur[k]-1][x],y); update(F[k],x,y); } } int main() { int x,y; while(~scanf("%d%d",&n,&q)) { init(); char s[3]; for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i