【BZOJ】3730: 震波

原题链接

题解

查询距离一个点距离在一定范围内的点,直接点分树,前缀和用树状数组维护
答案是当前重心距离不超过k - (x到重心距离)的点的前缀和,减去在x所在子树中,距离重心不超过k - (x到重心距离)的前缀和

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int lowbit(int x) {
    return x & (-x);
}
struct BIT {
    vector<int64> v;
    void init(int n) {
	for(int i = 1 ; i <= n + 1 ; ++i) v.pb(0);
    }
    void Insert(int x,int64 p) {
	while(x < v.size()) {
	    v[x] += p;
	    x += lowbit(x);
	}
    }
    int64 Query(int x) {
	int64 res = 0;
	x = min(x,(int)v.size() - 1);
	while(x > 0) {
	    res += v[x];
	    x -= lowbit(x);
	}
	return res;
    }
};
struct node {
    int to,next;
}E[MAXN * 2];
struct pdt {
    BIT rt,pre;
    vector<int> aux,sub,dep;
}tr[MAXN];
int head[MAXN],sumE;
int N,M,d[MAXN];
int64 val[MAXN];
bool vis[MAXN];
vector<int> poi;
void add(int u,int v) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    head[u] = sumE;
}
int Calc_G(int st) {
    static int fa[MAXN],siz[MAXN],son[MAXN],que[MAXN],ql,qr;
    ql = 1,qr = 0;
    que[++qr] = st;
    fa[st] = 0;siz[st] = 1;son[st] = 0;
    while(ql <= qr) {
	int u = que[ql++];
	for(int i = head[u] ; i ; i = E[i].next) {
	    int v = E[i].to;
	    if(v != fa[u] && !vis[v]) {
		fa[v] = u;siz[v] = 1;son[v] = 0;que[++qr] = v;
	    }
	}
    }
    int res = que[qr];
    for(int i = qr ; i >= 1 ; --i) {
	int u = que[i];
	if(fa[u]) {
	    siz[fa[u]] += siz[u];
	    son[fa[u]] = max(son[fa[u]],siz[u]);
	}
	son[u] = max(son[u],qr - siz[u]);
	if(son[u] < son[res]) res = u;
    }
    return res;
}
int get_max_dep(int u,int fa) {
    d[u] = d[fa] + 1;
    int res = d[u];
    poi.pb(u);
    for(int i = head[u] ; i ; i = E[i].next) {
	int v = E[i].to;
	if(!vis[v] && v != fa) {
	    res = max(res,get_max_dep(v,u));
	}
    }
    return res;
}
void dfs_divide(int u) {
    int G = Calc_G(u);
    vis[G] = 1;
    d[G] = 1;
    poi.clear();
    tr[G].rt.init(get_max_dep(G,0));
    for(int i = 0 ; i < poi.size() ; ++i) {
	tr[G].rt.Insert(d[poi[i]],val[poi[i]]);
	tr[poi[i]].aux.pb(G);
	tr[poi[i]].dep.pb(d[poi[i]]);
    }
    for(int i = head[G] ; i ; i = E[i].next) {
	int v = E[i].to;
	if(!vis[v]) {
	    int s = Calc_G(v);
	    poi.clear();
	    tr[s].pre.init(get_max_dep(v,G));
	    for(int j = 0 ; j < poi.size() ; ++j) {
		tr[poi[j]].sub.pb(s);
		tr[s].pre.Insert(d[poi[j]],val[poi[j]]);
	    }
	}
    }
    for(int i = head[G] ; i ; i = E[i].next) {
	int v = E[i].to;
	if(!vis[v]) dfs_divide(v);
    }
}
void Init() {
    read(N);read(M);
    int u,v;
    for(int i = 1 ; i <= N ; ++i) read(val[i]);
    for(int i = 1 ; i < N ; ++i) {
	read(u);read(v);
	add(u,v);add(v,u);
    }
    dfs_divide(1);
}
int64 Calc(int x,int k) {
    int64 res = 0;
    for(int i = tr[x].aux.size() - 1 ; i >= 0 ; --i) {
	int u = tr[x].aux[i];
	res += tr[u].rt.Query(k + 2 - tr[x].dep[i]);
    }
    for(int i = tr[x].sub.size() - 1 ; i >= 0 ; --i) {
	int u = tr[x].sub[i];
	res -= tr[u].pre.Query(k + 2 - tr[x].dep[i]);
    }
    return res;
}
void Change(int x,int y) {
    for(int i = tr[x].aux.size() - 1 ; i >= 0 ; --i) {
	int u = tr[x].aux[i];
	tr[u].rt.Insert(tr[x].dep[i],-val[x]);
	tr[u].rt.Insert(tr[x].dep[i],y);
    }
    for(int i = tr[x].sub.size() - 1 ; i >= 0 ; --i) {
	int u = tr[x].sub[i];
	tr[u].pre.Insert(tr[x].dep[i],-val[x]);
	tr[u].pre.Insert(tr[x].dep[i],y);
    }
    val[x] = y;
}
void Solve() {
    int la = 0;
    int x,op,y;
    for(int i = 1 ; i <= M ; ++i) {
	read(op);read(x);read(y);
	x = x ^ la;y = y ^ la;
	if(op == 0) {
	    la = Calc(x,y);
	    out(la);enter;
	}
	else {
	    Change(x,y);
	}
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}
posted @ 2019-04-02 11:49  sigongzi  阅读(282)  评论(0编辑  收藏  举报