Solution - P6329 【模板】点分树 | 震波

第一次见 WA 被伪装成 RE……

思路

点分树水题,只不过被 RE 卡了两个小时。(哭)

点分树节点上挂的数据结构变成了动态开点线段树而已。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
using namespace std;

#ifdef _WIN32
int stat_mem;
#endif

struct Node{
	int ls, rs;
	llong val;
} seg[N<<8];
int sub[N], all[N], tot;

int to[N<<1], nxt[N<<1], head[N], gsiz = 1;
#define mkarc(u,v) (++gsiz, to[gsiz]=v, nxt[gsiz]=head[u], head[u]=gsiz)
int siz[N], fa[N], dep[N], dis[N][20];
int a[N];
int n, q;

namespace segtree{
	#define mid (l+r>>1)
	#define pushup(x) (seg[x].val = seg[seg[x].ls].val + seg[seg[x].rs].val)
	inline void modify(rint& x, rint L, rint R, rint l, rint r, rllong k){
		if(x == 0) x = ++tot;
		if(L <= l && R >= r){
			seg[x].val += k;
			return;
		}
		if(L <= mid) modify(seg[x].ls, L, R, l, mid,   k);
		if(R >  mid) modify(seg[x].rs, L, R, mid+1, r, k);
		pushup(x);
		return;
	}
	inline llong query(rint x, rint L, rint R, rint l, rint r){
		if(x == 0) return 0;
		if(L <= l && R >= r)
			return seg[x].val;
		rllong res = 0;
		if(L <= mid) res += query(seg[x].ls, L, R, l, mid  );
		if(R >  mid) res += query(seg[x].rs, L, R, mid+1, r);
		return res;
	}
}
using namespace segtree;

namespace lca{
	int fa[N][21], dep[N];
	inline void init(rint u = 1, rint _fa = 0){
		if(u == 1) dep[u] = 1;
		for(rint i = 1; i <= 20; ++i)
			fa[u][i] = fa[fa[u][i-1]][i-1];
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(v == _fa) continue;
			fa[v][0] = u, dep[v] = dep[u]+1;
			init(v, u);
		}
		return;
	}
	inline int lca(rint u, rint v){
		if(dep[u] > dep[v]) swap(u, v);
		for(rint i = 20; i >= 0; --i)
			if(dep[fa[v][i]] >= dep[u]) v = fa[v][i];
		if(u == v) return u;
		for(rint i = 20; i >= 0; --i)
			if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
		return fa[u][0];
	}
	inline int dis(rint u, rint v){
		return dep[u]+dep[v]-2*dep[lca(u, v)];
	}
}

namespace divide{
	int vis[N];
	inline void dfs1(rint u, rint fa, rint sum, rint& minn, rint& g){
		rint mink = 0; siz[u] = 1;
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(vis[v] || v == fa) continue;
			dfs1(v, u, sum, minn, g);
			siz[u] += siz[v], mink = max(mink, siz[v]);
		}
		mink = max(mink, sum-siz[u]);
		if(mink < minn) g = u, minn = mink;
		return;
	}
	inline void dfs2(rint u, rint fa, rint dep, rint& seg1, rint& seg2){
		modify(seg1, dep, dep, 0, n, a[u]);
		modify(seg2, dep, dep, 0, n, a[u]);
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(v == fa || vis[v]) continue;
			dfs2(v, u, dep+1, seg1, seg2);
		}
		return;
	}
	inline void solve(rint u){
		vis[u] = true;
		modify(sub[u], 0, 0, 0, n, a[u]);
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(vis[v]) continue;
			rint minn = 1e9+7, g;
			dfs1(v, u, siz[v], minn, g);
			dfs1(g, u, siz[v], minn, g);
			dfs2(v, u, 1, all[g], sub[u]);
			dep[g] = dep[u]+1, fa[g] = u;
			solve(g);
		}
		return;
	}
}
using namespace divide;

#define getdis(u,v) (dis[u][dep[u]-dep[v]])
int code;

int main(){
	freopen("1.in", "r", stdin);
	scanf("%d %d", &n, &q);
	for(rint i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for(rint i = 1; i <  n; ++i){
		rint u, v;
		scanf("%d %d", &u, &v);
		mkarc(u, v), mkarc(v, u);
	}
	rint minn = 1e9+7, g;
	lca::init();
	dfs1(1, 0, n, minn, g);
	dfs1(g, 0, n, minn, g);
	dep[g] = 1;
	solve(g);
	for(rint i = 1; i <= n; ++i)
		for(rint j = fa[i]; j; j = fa[j])
			dis[i][dep[i]-dep[j]] = lca::dis(i, j);
	for(rint t = 1; t <= q; ++t){
		rint op, x, k;
		scanf("%d %d %d", &op, &x, &k);
		x ^= code, k ^= code;
		if(op == 0){
			rllong ans = 0;
			ans += query(sub[x], 0, k, 0, n);
			for(rint i = x; fa[i]; i = fa[i]){
				rint delta = getdis(x, fa[i]);
				if(k-delta < 0) continue;
				ans += query(sub[fa[i]], 0, k-delta, 0, n)-query(all[i], 0, k-delta, 0, n);
			}
			printf("%lld\n", ans);
			code = ans;
		}
		else{
			rllong delta = k-a[x]; a[x] = k;
			modify(sub[x], 0, 0, 0, n, delta);
			for(rint i = x; fa[i]; i = fa[i]){
				rint len = getdis(x, fa[i]);
				modify(sub[fa[i]], len, len, 0, n, delta);
				modify(all[i]    , len, len, 0, n, delta);
			}
		}
	}
	return 0;
}

posted @ 2025-05-22 20:15  Hootime  阅读(11)  评论(0)    收藏  举报