西南科技大学第十六届ACM程序设计竞赛暨绵阳市邀请赛 F 月出皎兮,佼人僚兮。
F
对于每一棵子树,考虑如何快速进行配对,ma为子树中权值最大的颜色的权值,sum为子树总权值,可以发现,如果ma>sum/2,那么这棵子树的答案就是sum-ma,否则答案就是sum/2。维护子树信息可以通过线段树合并或dsu on tree
线段树合并代码
#include <bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back #define mp make_pair #define fun function #define sz(x) (x).size() #define lowbit(x) (x)&(-x) #define all(x) (x).begin(),(x).end() #define mem(a,b) memset(a,b,sizeof(a)) namespace FastIO { #define BUF_SIZE 100000 #define OUT_SIZE 100000 bool IOerror=0; inline char nc() { static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if(p1==pend) { p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if(pend==p1) { IOerror=1; return -1; } } return *p1++; } inline bool blank(char ch) { return ch==' '||ch=='\n'||ch=='\r'||ch=='\t'; } template<class T> inline bool read(T &x) { bool sign=0; char ch=nc(); x=0; for(; blank(ch); ch=nc()); if(IOerror)return false; if(ch=='-')sign=1,ch=nc(); for(; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0'; if(sign)x=-x; return true; } template<class T,class... U>bool read(T& h,U&... t) { return read(h)&&read(t...); } #undef OUT_SIZE #undef BUF_SIZE }; using namespace std; using namespace FastIO; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); const int INF = 0x3f3f3f3f; const int N = 2e5+10; vector<int>e[N]; int ans[N],res; struct node { int l,r,ma; } tree[N * 40]; int a[N],w[N],siz[N]; int root[N],cnt; #define ls tree[x].l #define rs tree[x].r void ins(int &x,int l,int r,int pos,int val) { if(!x) x=++cnt; if(l==r) { tree[x].ma+=val; return ; } int mid=l+r>>1; if(pos<=mid) ins(ls,l,mid,pos,val); else ins(rs,mid+1,r,pos,val); tree[x].ma=max(tree[ls].ma,tree[rs].ma); } int merge(int x,int y,int l,int r) { if(!x || !y) return x+y; if(l==r) { tree[x].ma+=tree[y].ma; return x; } int mid=l+r>>1; tree[x].l=merge(tree[x].l,tree[y].l,l,mid); tree[x].r=merge(tree[x].r,tree[y].r,mid+1,r); tree[x].ma=max(tree[ls].ma,tree[rs].ma); return x; } void dfs(int u,int fa) { siz[u]=w[u]; ins(root[u],1,N,a[u],w[u]); for(auto v:e[u]) { if(v==fa) continue; dfs(v,u); siz[u]+=siz[v]; root[u]=merge(root[u],root[v],1,N); } int tot=tree[root[u]].ma; if(tot*2>=siz[u]) ans[u]=siz[u]-tot; else ans[u]=siz[u]/2; } int main() { #ifdef xiaofan freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif int n; read(n); for(int i=1; i<n; i++) { int u,v; read(u,v); e[u].pb(v); e[v].pb(u); } for(int i=1; i<=n; i++) read(a[i],w[i]); dfs(1,0); for(int i=1; i<=n; i++) printf("%d\n",ans[i]); return 0; }