BZOJ3730: 震波

BZOJ3730: 震波

https://lydsy.com/JudgeOnline/problem.php?id=3730

分析:

  • 对于点分树上的每个点\(x\),维护子树所有点到\(x\)的距离和到点分树上\(fa[x]\)的距离 。
  • 查询时查询\(x\)在点分树上到根的一条链,容斥计算答案。
  • 然后因为有修改我们使用树状数组。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
#define N 100050
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
	int x=0;
	char s=nc();
	while(s<'0') s=nc();
	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
	return x;
}
#define db(x) cerr<<#x<<" = "<<x<<endl
int head[N],to[N<<1],nxt[N<<1],cnt,n,m,val[N];
int siz[N],fk[N],root,tot,used[N],fa[N][20],dis[N][20],dep[N];
struct Bit {
	vector<int>b;
	void make(int s) {b.resize(s+2);}
	void fix(int x,int v) {
		x++;
		int lim=b.size();
		for(;x<lim;x+=x&(-x)) b[x]+=v;
	}
	int inq(int x) {
		x++;
		int re=0;
		x=min(x,int(b.size())-1);
		for(;x;x-=x&(-x)) re+=b[x];
		return re;
	}
}f1[N],f2[N];
inline void add(int u,int v) {
	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void gr(int x,int y) {
	int i;
	siz[x]=1; fk[x]=0;
	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
		gr(to[i],x); siz[x]+=siz[to[i]];
		fk[x]=max(fk[x],siz[to[i]]);
	}
	fk[x]=max(fk[x],tot-siz[x]);
	if(fk[root]>fk[x]) root=x;
}
int mxd;
void gd(int x,int y,int rt,int d) {
	int i;
	mxd=max(mxd,d);
	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
		mxd=max(mxd,dis[to[i]][dep[to[i]]]);
		fa[to[i]][++dep[to[i]]]=rt;
		dis[to[i]][dep[to[i]]]=d;
		gd(to[i],x,rt,d+1);
	}
}
void solve(int x) {
	used[x]=1;
	int i;
	mxd=0;
	gd(x,0,x,1);
	f1[x].make(mxd); f2[x].make(mxd);
	int all=tot;
	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
		tot=siz[to[i]]; 
		root=0; gr(to[i],x); solve(root);
	}
}
void upd(int x,int v) {
	int i;
	f1[x].fix(0,v);
	f2[x].fix(dis[x][dep[x]],v);
	for(i=dep[x];i;i--) {
		f1[fa[x][i]].fix(dis[x][i],v);
		f2[fa[x][i]].fix(dis[x][i-1],v);
	}
}
int query(int x,int k) {
	int i,re=f1[x].inq(k);
	for(i=dep[x];i;i--) {
		if(k>=dis[x][i]) {
			re+=f1[fa[x][i]].inq(k-dis[x][i]);
			re-=f2[fa[x][i+1]].inq(k-dis[x][i]);
		}
	}
	return re;
}
int main() {
	n=rd(),m=rd();
	int i,x,y,opt;
	for(i=1;i<=n;i++) val[i]=rd();
	for(i=1;i<n;i++) {
		x=rd(), y=rd();
		add(x,y); add(y,x);
	}
	tot=n;
	fk[0]=1ll<<30;
	gr(1,0);
	solve(root);
	for(i=1;i<=n;i++) fa[i][dep[i]+1]=i;
	for(i=1;i<=n;i++) upd(i,val[i]);
	int ans=0;
	while(m--) {
		opt=rd(), x=rd(), y=rd();
		x^=ans, y^=ans;
		if(!opt) {
			ans=query(x,y);
			printf("%d\n",ans);
		}else {
			upd(x,y-val[x]), val[x]=y;
		}
	}
}

posted @ 2018-12-23 15:12  fcwww  阅读(237)  评论(0编辑  收藏  举报