洛谷 P4178 Tree
作者:互联网
首先点分治;
由于求解的是小于等于k的个数,于是开一个树状数组维护前缀和即可;
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 20009
#define MS 40009
int n,m;
struct node{
int to,val;
};
vector<node > vc[MS];
int sz[MS],w[MS];
int rt,tr_size;
int del[MS];
int dis[MS];
int dislist[MS] ,cntd;
int ext[MAXN];
queue<int > Q;
LL ans;
int p[MAXN]; // 树状数组
int lowbit(int x){
return x&(-x);
}
void add(int pos,int val){
for(;pos<=20000;pos+=lowbit(pos)) p[pos] += val;
}
int get_sum(int pos){
int ans = 0;
for(;pos;pos-=lowbit(pos)) ans += p[pos];
return ans;
}
void get_rt(int u,int f){
sz[u] = 1;
w[u] = 0;
for(auto &nb:vc[u]){
int v = nb.to;
if(v != f && !del[v]){
get_rt(v,u);
sz[u] += sz[v];
w[u] = max(w[u],sz[v]);
}
}
w[u] = max(w[u],tr_size-sz[u]);
if(w[u] < w[rt]) rt = u;
}
void get_dis(int u,int f){
if(dis[u] <= m) dislist[++cntd] = dis[u];
for(auto &nb:vc[u]){
int v = nb.to;
int val = nb.val;
if(v != f && !del[v]){
dis[v] = dis[u] + val;
get_dis(v,u);
}
}
}
void cal(int u){
ext[0]++;
add(1,1); // +1方便树状数组维护
for(auto &nb:vc[u]){
int v = nb.to;
int val = nb.val;
if(!del[v]){
cntd = 0;
dis[v] = val;
get_dis(v,u);
for(int i=1;i<=cntd;i++){
ans += get_sum(m-dislist[i]+1); // 树状数组求前缀和
}
for(int i=1;i<=cntd;i++){
ext[dislist[i]]++;
add(dislist[i]+1,1);
Q.push(dislist[i]);
}
}
}
ext[0]--;
add(1,-1);
while(!Q.empty()){
ext[Q.front()]--;
add(Q.front()+1,-1);
Q.pop();
}
}
void divide(int u){
del[u] = 1;
cal(u);
for(auto &nb:vc[u]){
int v = nb.to;
if(!del[v]){
w[rt = 0] = tr_size = sz[v];
get_rt(v,0);
get_rt(rt,0);
divide(rt);
}
}
}
void solve(){
cin >> n;
for(int i=2;i<=n;i++){
int u,v,val;
cin >> u >> v >> val;
vc[u].push_back({v,val});
vc[v].push_back({u,val});
}
cin >> m;
w[rt = 0] = tr_size = n;
get_rt(1,0);
get_rt(rt,0);
divide(rt);
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);
int ce;
// cin >> ce;
ce = 1;
while(ce--){
solve();
}
return 0;
}
标签:rt,vc,洛谷,val,int,Tree,ce,MS,P4178 来源: https://www.cnblogs.com/Tecode/p/15043316.html