NOIP 模擬 $83\; \rm 時代的眼淚$
阿新 • • 發佈:2021-10-26
題解
題解 \(by\;zj\varphi\)
答案可以轉化為,每個點的子樹中小於子樹的根的數量的和。
可以先用權值樹狀陣列求出來 1 的答案,然後再用換根 dp 解決。
\(dp_v=dp_x+low_{1,v}-low_{v,v}-low_{v,x}\)
其中 \(low_{x,v}\) 表示在以 x 為根的子樹中,有多少小於 \(w_v\) 的值。
複雜度 \(\mathcal{O\rm{(nlogn)}}\)。
Code
#include<bits/stdc++.h> #define ri signed #define pd(i) ++i #define bq(i) --i #define func(x) std::function<x> namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++ #define debug1(x) std::cerr << #x"=" << x << ' ' #define debug2(x) std::cerr << #x"=" << x << std::endl #define Debug(x) assert(x) struct nanfeng_stream{ template<typename T>inline nanfeng_stream &operator>>(T &x) { bool f=false;x=0;char ch=gc(); while(!isdigit(ch)) f|=ch=='-',ch=gc(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc(); return x=f?-x:x,*this; } }cin; } using IO::cin; namespace nanfeng{ #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} using ll=long long; static const int N=1e6+7; struct edge{int v,nxt,w;}e[N<<1]; int first[N],t=1,st[N],w[N],siz[N],n,q; ll ans[N],as; auto add=[](int u,int v) { e[t]={v,first[u],0},first[u]=t++; e[t]={u,first[v],0},first[v]=t++; }; struct BIT{ #define lowbit(x) ((x)&-(x)) int c[N]; func(void(void)) init=[&]() {memset(c,0,sizeof(c));}; func(void(int,int)) update=[&](int x,int k) {for (;x<=n;x+=lowbit(x)) c[x]+=k;}; func(int(int)) query=[&](int x) { // Debug(x>=0); int res=0; for (;x;x-=lowbit(x)) res+=c[x]; return res; }; }B; func(void(int,int)) dfs=[](int x,int fa) { B.update(w[x],1); int lft=B.query(w[x]-1),kl=lft; for (ri i(first[x]),v;i;i=e[i].nxt) { if ((v=e[i].v)==fa) continue; dfs(v,x); int nw=B.query(w[x]-1); e[i].w=nw-kl; kl=nw; } siz[x]=B.query(w[x]-1)-lft; ans[1]+=siz[x]; }; func(void(int,int)) solve=[](int x,int fa) { for (ri i(first[x]),v;i;i=e[i].nxt) { if ((v=e[i].v)==fa) continue; ans[v]=ans[x]-e[i].w+B.query(w[v]-1)-siz[v]; solve(v,x); } }; inline int main() { FI=freopen("tears.in","r",stdin); FO=freopen("tears.out","w",stdout); cin >> n >> q; for (ri i(1);i<=n;pd(i)) cin >> w[i],st[i]=w[i]; std::sort(st+1,st+n+1); int k=std::unique(st+1,st+n+1)-st; for (ri i(1);i<=n;pd(i)) w[i]=std::lower_bound(st+1,st+k,w[i])-st; for (ri i(1),u,v;i<n;pd(i)) cin >> u >> v,add(u,v); dfs(1,0); solve(1,0); for (ri i(1),u;i<=q;pd(i)) cin >> u,printf("%lld\n",ans[u]); return 0; } } int main() {return nanfeng::main();}