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;
}