题解:P9260 [PA 2022] Miny
题目描述
有一颗
问题分析
我们可以建一个有向图
(这张图代表的是实点
通过前缀和与点分治优化建图我们可以将
CODE
#include<bits/stdc++.h>
using namespace std;
namespace fastio{
#define il inline
const int isz=1<<25;
char iin[isz],*is=iin+isz,*it=iin+isz;
#define gc() (is==it)?(it=(is=iin)+fread(iin,1,isz,stdin),(is==it)?EOF:*is++):*is++
template<typename T> il void rd(T &x){
x=0;
char c=gc();
bool fla=false;
while(!isdigit(c)) fla|=(c=='-'),c=gc();
while(isdigit(c)) x=(x<<1)+(x<<3)+(c&15),c=gc();
x=(fla)?-x:x;
}
template<typename T1,typename...T2> il void rd(T1 &x,T2&...y){rd(x);rd(y...);}
template<typename T> il void rd(T a[],T s,T t){for(T i=s;i<=t;i++) rd(a[i]);}
char iout[isz],*ita=iout;
#define Flush() fwrite(iout,1,ita-iout,stdout);ita=iout
template<typename T> il void wr(T x,char la='\n'){
char c[35];
int len=0;
if(x<0) *ita++='-',x=-x;
do{c[++len]=(x%10+'0');x/=10;}while(x);
while(len)*ita++=c[len--];
*ita++=la;
}
il void en(char x){*ita++=x;}
}
using namespace fastio;
const int N=1e5+5,bl=2000;
#define int long long
int n,r[N],sz[N],del[N],dis[N],vir[N],tot,dfn[20*N],low[20*N],in[20*N],idx,id[20*N],scc,num,ans[N];
vector<int> e[N],w[N],g[20*N];
vector<pair<int,int> > line;
stack<int> q;
pair<int,int> s[400*N];
bitset<bl+10> f[20*N];
int rt_check(int x,int fa,int y,int &rt){
sz[x]=1;
int maxx=0;
for(auto i:e[x])if(i!=fa&&!del[i]){rt_check(i,x,y,rt);sz[x]+=sz[i];maxx=max(maxx,sz[i]);}
maxx=max(maxx,y-sz[x]);
if((maxx<<1)<=y) rt=x;
return sz[x];
}
void cal(int x,int fa){
sz[x]=1;
line.push_back({dis[x],x});
for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa&&!del[e[x][i]]){dis[e[x][i]]=dis[x]+w[x][i];cal(e[x][i],x);sz[x]+=sz[e[x][i]];}
}
void dfs(int x,int sz){
if(sz==1) return;
int rt;
rt_check(x,x,sz,rt);
del[rt]=1;
dis[rt]=0;
line.clear();
cal(rt,rt);
sort(line.begin(),line.end());
memset(vir,0,sizeof vir);
for(auto i:line){
int ttt=upper_bound(line.begin(),line.end(),make_pair(r[i.second]-dis[i.second],n+1))-line.begin();
ttt--;
if(ttt>=0){if(!vir[ttt]){vir[ttt]=++tot;g[tot].push_back(line[ttt].second);}g[i.second].push_back(vir[ttt]);}
}
int la=-1;
for(int i=line.size()-1;i>=0;i--)
if(vir[i]){
if(la!=-1){
g[vir[la]].push_back(vir[i]);
for(int j=i+1;j<la;j++) g[vir[la]].push_back(line[j].second);
}
la=i;
}
if(la!=-1)for(int j=0;j<la;j++)g[vir[la]].push_back(line[j].second);
for(auto i:e[rt]) if(!del[i]) dfs(i,::sz[i]);
}
void tarjan(int x){
dfn[x]=low[x]=++idx;
in[x]=1;
q.push(x);
for(auto i:g[x]){if(!dfn[i]){tarjan(i);low[x]=min(low[x],low[i]);}else if(in[i])low[x]=min(low[x],dfn[i]);}
if(low[x]==dfn[x]){++scc;int ttt;do{ttt=q.top();q.pop();in[ttt]=0;id[ttt]=scc;}while(ttt!=x);}
}
signed main(){
rd(n);
rd(r,1ll*1,n);
for(int i=1;i<n;i++){int x,y,z;rd(x,y,z);e[x].push_back(y);e[y].push_back(x);w[x].push_back(z);w[y].push_back(z);}
tot=n;
dfs(1,n);
for(int i=1;i<=tot;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=tot;i++) for(auto j:g[i]) if(id[i]!=id[j]) s[num++]={id[j],id[i]};
int maxn=0;
for(int i=1;i<=n;i++) maxn=max(maxn,id[i]);
sort(s,s+num);
num=unique(s,s+num)-s;
auto solve=[maxn](int l,int r){
for(int i=1;i<=maxn;i++) f[i].reset();
for(int i=l;i<=r;i++) f[id[i]].set(i-l);
for(int i=0;i<num;i++) f[s[i].second]|=f[s[i].first];
for(int i=1;i<=n;i++) ans[i]+=f[id[i]].count();
};
for(int i=1;i<=n;i+=bl) solve(i,min(i+bl-1,n));
for(int i=1;i<=n;i++) wr(ans[i],' ');
Flush();
return 0;
}