动态点分治
例题:lgP6329 【模板】点分树 | 震波
题意:给你一颗形态固定的树支持两个操作
1.每次问你距离一个节点 \(<=k\)的节点的权值和
2.修改一个节点的权值
sol.首先发现,要是每一个都拿点分治来处理,肯定会T飞
并且发现 点分治都过程重复了很多次
不妨先把点分治 的关系树建出来
发现 至多有logn层
直接在上面跑 就好了
(太久没打 码力题,水平下降严重)
真心调不动
#include<bits/stdc++.h>
#define MAXN 800005
#define INF 0x3f3f3f3f
using namespace std;
int n,m,a[MAXN];
vector<int>G[MAXN],G2[MAXN];
int sz[MAXN],val[MAXN],vis[MAXN],f[MAXN][25],dep[MAXN];
int FA[MAXN];
int lca(int x , int y){
if(dep[x] < dep[y])swap(x , y);
int dx = dep[x] - dep[y];
for(int i = 0 ; i <= 20 ; i++)if(dx & (1 << i))x = f[x][i];
if(x == y)return x;
for(int i = 20 ; i >= 0 ; i--)if(f[x][i] != f[y][i])x = f[x][i] , y = f[y][i];
return f[x][0];
}
int dis(int x , int y){return dep[x] + dep[y] - 2 * dep[lca(x , y)];}
void get_fa(int now , int fa){
cout<<now<<endl;
dep[now] = dep[fa] + 1;
f[now][0] = fa;
for(auto v : G[now]){
if(v == fa)continue;
if(dep[v])continue;
get_fa(v , now);
}
}
void get_sz(int now , int fa){
sz[now] = 1;
for(auto v : G[now]){
if(v == fa)continue;
if(vis[v])continue;
get_sz(v , now);
sz[now] += sz[v];
}
}
int zx;
void get_zx(int now , int fa , int yl){
for(auto v : G[now]){
if(v == fa)continue;
if(vis[v])continue;
get_zx(v , now , yl);
val[now] = max(val[now] , sz[v]);
}
val[now] = max(val[now] , sz[yl] - sz[now]);
if(val[zx] > val[now])zx = now;
}
void solve(int now){
vis[now] = 1;
for(auto v : G[now]){
if(vis[v])continue;
get_sz(v , now);
zx = 0;
get_zx(v , now , v);
solve(zx);
G2[now].push_back(zx);
G2[zx].push_back(now);
}
}
void dfs_init(int now , int fa){
FA[now] = fa;
for(auto v : G2[now]){
if(v == fa)continue;
dfs_init(v , now);
}
}
struct ST{
int dex,RT[MAXN];
struct node2{int lc,rc,val;}t[MAXN * 25];
int update(int rt , int l , int r , int x , int y){
if(!rt)rt = ++dex;
if(l == r){
t[rt].val += y;
return rt;
}
int mid = (l + r) >>1;
if(x <= mid)t[rt].lc = update(t[rt].lc , l , mid , x , y);
else t[rt].rc = update(t[rt].rc , mid + 1 , r , x , y);
t[rt].val = t[t[rt].lc].val + t[t[rt].rc].val;
return rt;
}
int que(int rt , int l , int r , int x , int y){
if(!rt)return 0;
if(x <= l && r <= y)return t[rt].val;
int mid = (l + r) >> 1;
return que(t[rt].lc , l , mid , x , y) + que(t[rt].rc , mid + 1 , r , x , y);
}
}T0,T1;
int main(){
freopen("P6329_1.in" , "r" , stdin);
scanf("%d%d" , &n , &m);int x,y;val[0] = INF;
for(int i = 1 ; i <= n ; i++)scanf("%d" , &a[i]);
for(int i = 1 ; i < n ; i++){
scanf("%d%d" , &x , &y);
G[x].push_back(y);
G[y].push_back(x);
}
get_fa(1 , 1);
zx = 0 , get_sz(1 , 1) , get_zx(1 , 1 , 1);
solve(zx);
dfs_init(1 , -1);
for(int j = 1 ; j <= 20 ; j++)
for(int i = 1 ; i <= n ; i++)
f[i][j] = f[f[i][j - 1]][j - 1];
for(int i = 1 ; i <= n ; i++){
int now = i;
while(now != (-1)){
T0.RT[now] = T0.update(T0.RT[now] , 0 , n - 1 , dis(now , i) , a[i]);
if(FA[now] != (-1))T1.RT[now] = T1.update(T1.RT[now] , 0 , n - 1 , dis(FA[now] , i) , a[i]);
now = FA[now];
}
}
int op,k;
while(m--){
scanf("%d%d%d" , &op , &x , &y);
if(op == 0){
k = y;
int now = x , zz = 0 , pre = 0;
while(now != (-1)){
if(dis(now , x) > k){
pre = now , now = FA[now];
continue;
}
zz = zz + T0.que(T0.RT[now] , 0 , n - 1 , 0 , k - dis(now , x));
if(pre)zz = zz - T1.que(T1.RT[pre] , 0 , n - 1 , 0 , k - dis(now , x));
now = FA[now];
}
cout<<zz<<endl;
}
else{
}
}
}

浙公网安备 33010602011771号