最近学习了一下动态树分治。刷了一些比较基础的题目
一般都是存一下到这个重心的信息,然后再存这棵子树到上一层重心的信息,搞一搞就可以了
[COGS 2278]树黑白
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 200010
using namespace std;
typedef long long ll;
int n, m;
//-------------------------------------------------//
struct Edge{int to, nxt, dis;}edge[maxn << 1];
int h[maxn], cnt;
void add(int u, int v, int d){
cnt ++;
edge[cnt].to = v;
edge[cnt].nxt = h[u];
edge[cnt].dis = d;
h[u] = cnt;
}
//-------------------------------------------------//
ll dis[maxn];
int dep[maxn], fa[maxn], anc[maxn][20];
void dfs(int u){
dep[u] = dep[fa[u]] + 1;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(v == fa[u])continue;
dis[v] = dis[u] + edge[i].dis;
fa[v] = u;
dfs(v);
}
}
int ask_LCA(int p, int q){
if(dep[p] < dep[q])swap(p, q);
int log = 1;
for(; 1 << log <= dep[p]; log ++); log --;
for(int i = log; i >= 0; i --)
if(anc[p][i] && dep[anc[p][i]] >= dep[q])
p = anc[p][i];
if(p == q)return p;
for(int i = log; i >= 0; i --)
if(anc[p][i] && anc[p][i] != anc[q][i])
p = anc[p][i], q = anc[q][i];
return fa[p];
}
ll dist(int p, int q){return dis[p] + dis[q] - 2 * dis[ask_LCA(p, q)];}
//-------------------------------------------------//
int g[maxn], size[maxn], G, Sum;
bool vis[maxn], check[maxn];
void Get_G(int u, int fa){
size[u] = 1;
int f = 0;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(v == fa || vis[v])continue;
Get_G(v, u);
size[u] += size[v];
f = max(f, size[v]);
}
f = max(f, Sum - size[u]);
if((f << 1) <= Sum)G = u;
}
void Divide(int u, int f){
g[u] = f;
vis[u] = true;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v])continue;
Sum = size[v], G = v;
Get_G(v, u);
Divide(G, u);
}
}
//-------------------------------------------------//
ll Node[maxn], Dis[maxn], Disf[maxn], ans;
int Standard;
void White(int u){
Node[u] --;
Dis[u] -= dist(u, Standard);
if(g[u] == -1)return;
Disf[u] -= dist(g[u], Standard);
White(g[u]);
}
void Black(int u){
Node[u] ++;
Dis[u] += dist(u, Standard);
if(g[u] == -1)return;
Disf[u] += dist(g[u], Standard);
Black(g[u]);
}
void ask(int u){
ans += (Node[u] * dist(u, Standard) + Dis[u]);
if(g[u] == -1)return;
ans -= (Node[u] * dist(g[u], Standard) + Disf[u]);
ask(g[u]);
}
int main(){
freopen("A_Tree.in", "r", stdin);
freopen("A_Tree.out", "w", stdout);
scanf("%d%d", &n, &m);
int u, v, d;
for(int i = 1; i < n; i ++){
scanf("%d%d%d", &u, &v, &d);
add(u, v, d), add(v, u, d);
}
dfs(1); Sum = n;
Get_G(1, -1), Divide(G, -1);
for(int i = 1; i <= n; i ++)
anc[i][0] = fa[i];
for(int j = 1; 1 << j <= n; j ++)
for(int i = 1; i <= n; i ++)
anc[i][j] = anc[anc[i][j-1]][j-1];
char cmd[2];
while(m --){
scanf("%s%d", cmd, &u);
Standard = u;
if(cmd[0] == 'Q'){
ans = 0;
ask(u);
printf("%lld\n", ans);
}
else{
if(check[u])White(u);
else Black(u);
check[u] ^= 1;
}
}
return 0;
}
[COGS 2258]复仇的序幕曲
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define maxn 100010
using namespace std;
struct Edge{int to, nxt, dis;}edge[maxn << 1];
int h[maxn], cnt;
void add(int u, int v, int d){
cnt ++;
edge[cnt].to = v;
edge[cnt].nxt = h[u];
edge[cnt].dis = d;
h[u] = cnt;
}
int n, m, a[maxn];
int dis[maxn], fa[maxn], anc[maxn][20], dep[maxn];
void dfs(int u){
dep[u] = dep[fa[u]] + 1;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(v == fa[u])continue;
fa[v] = u;
dis[v] = dis[u] + edge[i].dis;
dfs(v);
}
}
int ask_LCA(int p, int q){
if(dep[p] < dep[q])swap(p, q);
int log = 1;
for(; 1 << log <= dep[p]; log ++); log --;
for(int i = log; i >= 0; i --)
if(anc[p][i] && dep[anc[p][i]] >= dep[q])
p = anc[p][i];
if(p == q)return p;
for(int i = log; i >= 0; i --)
if(anc[p][i] && anc[p][i] != anc[q][i])
p = anc[p][i], q = anc[q][i];
return fa[p];
}
int dist(int p, int q){
return dis[p] + dis[q] - 2 * dis[ask_LCA(p, q)];
}
//-----------------------------------------------//
bool vis[maxn];
int g[maxn], size[maxn], G, Sum;
vector<pair<int, int> > V[maxn], F[maxn];
void Get_G(int u, int fa){
int f = 0; size[u] = 1;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v] || v == fa)continue;
Get_G(v, u);
size[u] += size[v];
f = max(f, size[v]);
}
f = max(f, Sum - size[u]);
if((f << 1) <= Sum) G = u;
}
void Divide(int u, int f){
g[u] = f, vis[u] = true;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v])continue;
Sum = size[v], G = v;
Get_G(v, u), Divide(G, u);
}
}
int st, T, ans;
void update(int u){
V[u].push_back(make_pair(dist(st, u), a[st]));
F[u].push_back(make_pair(dist(st, g[u]), a[st]));
if(g[u] > 0)update(g[u]);
}
int Binarysearch(vector<pair<int, int> > &V, int nw){
if(V[0].first > nw)return 0;
int l = 0, r = V.size() - 1;
while(l < r){
int m = l + (r - l + 1) / 2;
if(V[m].first > nw)
r = m - 1;
else l = m;
}
return V[l].second;
}
void ask(int u){
ans += Binarysearch(V[u], T - dist(u, st));
if(g[u] == -1)return;
int d = dist(g[u], st);
ans -= Binarysearch(F[u], T - d);
ask(g[u]);
}
//-----------------------------------------------//
int main(){
freopen("SS.in", "r", stdin);
freopen("SS.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
int u, v, d;
for(int i = 1; i < n; i ++){
scanf("%d%d%d", &u, &v, &d);
add(u, v, d), add(v, u, d);
}
dfs(1);
for(int i = 1; i <= n; i ++)
anc[i][0] = fa[i];
for(int j = 1; 1 << j <= n; j ++)
for(int i = 1; i <= n; i ++)
anc[i][j] = anc[anc[i][j-1]][j-1];
Sum = n;
Get_G(1, -1), Divide(G, -1);
for(int i = 1; i <= n; i ++)
st = i, update(i);
int sum = 0;
for(int i = 1; i <= n; i ++){
sort(V[i].begin(), V[i].end());
sort(F[i].begin(), F[i].end());
sum = 0;
for(int j = 0; j < V[i].size(); j ++){
sum += V[i][j].second;
V[i][j].second = sum;
}
sum = 0;
for(int j = 0; j < F[i].size(); j ++){
sum += F[i][j].second;
F[i][j].second = sum;
}
}
while(m --){
scanf("%d%d", &st, &T);
ans = 0, ask(st);
printf("%d\n", ans);
}
return 0;
}
[HNOI 2015]开店
并不清楚为什么要写G=v;这句话,难道找不到么。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define maxn 150010
using namespace std;
typedef long long ll;
typedef vector<pair<int, ll> > vp;
int n, Q, A;
struct Edge{int to, nxt, dis;}edge[maxn << 1];
int h[maxn], cnt;
void add(int u, int v, int w){
cnt ++;
edge[cnt].to = v;
edge[cnt].nxt = h[u];
edge[cnt].dis = w;
h[u] = cnt;
}
int a[maxn];
//-----------------------------------------------------//
int dep[maxn], fa[maxn], anc[maxn][20];
ll dis[maxn];
void dfs(int u){
dep[u] = dep[fa[u]] + 1;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(v == fa[u])continue;
fa[v] = u;
dis[v] = dis[u] + edge[i].dis;
dfs(v);
}
}
void pre_LCA(){
for(int i = 1; i <= n; i ++)
anc[i][0] = fa[i];
for(int j = 1; 1 << j <= n; j ++)
for(int i = 1; i <= n; i ++)
anc[i][j] = anc[anc[i][j-1]][j-1];
}
int ask_LCA(int p, int q){
if(dep[p] < dep[q])swap(p, q);
int log = 1;
for(; 1 << log <= dep[p]; log ++); log --;
for(int i = log; i >= 0; i --)
if(anc[p][i] && dep[anc[p][i]] >= dep[q])
p = anc[p][i];
if(p == q)return p;
for(int i = log; i >= 0; i --)
if(anc[p][i] && anc[p][i] != anc[q][i])
p = anc[p][i], q = anc[q][i];
return fa[p];
}
ll dist(int u, int v){
return dis[u] + dis[v] - 2 * dis[ask_LCA(u, v)];
}
//-----------------------------------------------------//
int g[maxn], size[maxn], G, Sum;
vp V[maxn], F[maxn];
bool vis[maxn];
void Get_G(int u, int fa){
size[u] = 1; int f = 0;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(v == fa || vis[v])continue;
Get_G(v, u);
size[u] += size[v];
f = max(f, size[v]);
}
f = max(f, Sum - size[u]);
if((f << 1) <= Sum)G = u;
}
void Divide(int u, int f){
g[u] = f, vis[u] = true;
for(int i = h[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v])continue;
Sum = size[v], G = v;
Get_G(v, u), Divide(G, u);
}
}
int St;
void update(int u){
V[u].push_back(make_pair(a[St], dist(St, u)));
if(g[u] < 0) return;
F[u].push_back(make_pair(a[St], dist(St, g[u])));
update(g[u]);
}
ll ans = 0;
int L, R;
int Bs(vp& V, ll nw){
int l = 0, r = V.size() - 1;
while(l < r){
int m = l + (r - l + 1) / 2;
if(V[m].first <= nw)l = m;
else r = m - 1;
}
return l;
}
ll Binarysearch(vp &V, ll dis){
if(V[0].first > R)return 0;
if(V[V.size()-1].first < L)return 0;
int ret1 = Bs(V, L-1), ret2 = Bs(V, R);
return dis * (ret2 - ret1) + V[ret2].second - V[ret1].second;
}
void ask(int u){
ans += Binarysearch(V[u], dist(St, u));
if(g[u] < 0)return;
ans -= Binarysearch(F[u], dist(St, g[u]));
ask(g[u]);
}
int main(){
freopen("shop_hnoi2015.in", "r", stdin);
freopen("shop_hnoi2015.out", "w", stdout);
scanf("%d%d%d", &n, &Q, &A);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
int u, v, d;
for(int i = 1; i < n; i ++){
scanf("%d%d%d", &u, &v, &d);
add(u, v, d), add(v, u, d);
}
dfs(1), pre_LCA(), Sum = n;
Get_G(1, -1), Divide(G, -1);
for(int i = 1; i <= n; i ++)
update(St = i);
for(int i = 1; i <= n; i ++){
V[i].push_back(make_pair(-1, 0));
F[i].push_back(make_pair(-1, 0));
sort(V[i].begin(), V[i].end());
sort(F[i].begin(), F[i].end());
for(int j = 1; j < V[i].size(); j ++)
V[i][j].second += V[i][j-1].second;
for(int j = 1; j < F[i].size(); j ++)
F[i][j].second += F[i][j-1].second;
}
while(Q --){
scanf("%d%d%d", &u, &L, &R);
L = (L + ans) % A, R = (R + ans) % A;
if(L > R)swap(L, R);
St = u, ans = 0, ask(u);
printf("%lld\n", ans);
}
return 0;
}