CF516D Drazil and Morning Exercise 题解
安利\(:\) 杂题选做
不难发现权值分布组成了一棵以\(f_x\)最小的\(x\)为根的树\(,\)其中父亲的权值一定\(\leq\)儿子的权值\(.\)
那么直接\(two-pointers,\)然后用并查集维护当前的答案就可以做到 \(O(nα(n))\)处理一组询问 \(.\)
\(two-pointers\)的细节大概是\(,\)考虑\(l,r\)的移动\(,\) 不难发现\(r\)变小是不会影响联通情况的\(,\)所以就从大往小扫\(.\)
复杂度 \(O(qnα(n)).\)
代码 \(:\)
#include <bits/stdc++.h>
#define LL long long
using namespace std;
template <typename T> void read(T &x){
x = 0; int f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
const int N = 100050;
int To[N<<1],Ne[N<<1],Dis[N<<1],He[N],_;
inline void add(int x,int y,int w){
++_; To[_] = y,Ne[_] = He[x],Dis[_] = w,He[x] = _;
++_; To[_] = x,Ne[_] = He[y],Dis[_] = w,He[y] = _;
}
int n; LL a[N]; int p[N],fa[N],dpt[N]; vector<int>ch[N];
inline bool cmp(int x,int y){ return (a[x] != a[y]) ? (a[x] > a[y]) : (dpt[x] > dpt[y]); }
struct DS{
int cnt[N],ans,fa[N],size[N];
inline void init(){ memset(cnt,0,(n+1)<<2),ans = 0; for (int i = 1; i <= n; ++i) fa[i] = i,size[i] = 1,++cnt[1]; }
inline int Find(int x){ return x == fa[x] ? x : (fa[x] = Find(fa[x])); }
inline void Merge(int x,int y){
x = Find(x),y = Find(y); if (x == y) return;
if (size[x] > size[y]) swap(x,y);
--cnt[size[x]],--cnt[size[y]]; size[y] += size[x]; ++cnt[size[y]];
ans = max(ans,size[y]);
fa[x] = y;
}
inline void Dec(int x){
x = Find(x); --cnt[size[x]];
if (size[x] == ans && !cnt[size[x]]) --ans;
--size[x]; ++cnt[size[x]];
}
inline int Ans(){ return ans; }
}T;
namespace subtask1{
LL dis[N];
inline void dfs(int x,int f){ if (f == -1) dis[x] = 0; for (int y,p = He[x]; p ; p = Ne[p]) if ((y=To[p])^f) dis[y] = dis[x] + Dis[p],dfs(y,x); }
inline void solve(){
int i,mx,x,y;
dfs(1,-1); for (mx = 1,i = 2; i <= n; ++i) if (dis[i] > dis[mx]) mx = i;
x = mx,dfs(x,-1); for (mx = 1,i = 2; i <= n; ++i) if (dis[i] > dis[mx]) mx = i; y = mx;
for (i = 1; i <= n; ++i) a[i] = dis[i];
dfs(y,-1); for (i = 1; i <= n; ++i) a[i] = max(a[i],dis[i]);
}
}
inline void dfs(int x){
dpt[x] = dpt[fa[x]]+1;
for (int y,p = He[x]; p ; p = Ne[p]) if ((y=To[p])^fa[x]) fa[y] = x,dfs(y),ch[x].push_back(y);
}
inline int solve(LL d){
int ans = 1,l,r,x,i;
T.init();
for (l = r = 1; l <= n; ++l){
while (r < n && a[p[l]]-a[p[r+1]] <= d){
++r; x = p[r];
for (i = 0; i < ch[x].size(); ++i) T.Merge(x,ch[x][i]);
}
ans = max(ans,T.Ans());
T.Dec(p[l]);
}
return ans;
}
int main(){
int i,x,y,z,Rt;
read(n);
for (i = 1; i < n; ++i) read(x),read(y),read(z),add(x,y,z);
subtask1::solve();
for (Rt = 1,i = 2; i <= n; ++i) if (a[i] < a[Rt]) Rt = i;
dfs(Rt);
for (i = 1; i <= n; ++i) p[i] = i;
sort(p+1,p+n+1,cmp);
int q; LL v;
read(q); while (q--) read(v),write(solve(v)),putchar('\n');
return 0;
}