CF1320E Treeland and Viruses 題解
阿新 • • 發佈:2021-09-24
Link.
Description.
多次詢問,每次給出一些源點一些詢問點。
多輪擴充套件,初始每個源點有它的顏色,每輪按照輸入順序依次擴充套件。
每次擴充套件所有到已是它顏色的距離不超過 \(s_i\) 的無色點,問詢問點最後是什麼顏色。
Solution.
多次直接套虛樹,然後就變成了要求 \(O(\text{點數})\) 得到最後點是什麼顏色。
考慮一個 \(O(Q\cdot m)\) 的做法,就是對於每個詢問可以 \(O(m)\) 列舉。
對於一個詢問的一個可行方案,可以 \(O(\log n)\) 或 \(O(1)\) 求出顏色到它的時間。
然後就可以快速比較兩種顏色的優先程度了。
考慮優化,如果一個顏色在某個地方已經被覆蓋了,就可以不用考慮它了。
考慮一個顏色的覆蓋路徑,肯定是一條鏈,鏈又可以分成兩段一段是上行一段是下行。
考慮記錄當前這個點的顏色,然後從下到上更新父親,從上到下更新兒子。
然後就做完了。
程式碼長度竟然主要是虛樹,這是沒想到的啊。。。
Coding.
點選檢視太弱程式碼
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{ #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; } template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}} const int N=200005;int n,Q,K,m,F[N],cl[N],idt,id[N<<2],sp[N],qr[N],fa[N],st[N],tp; struct edge{int to,nxt;}e[N<<1];int et,head[N],f[N][20],dep[N],dt,dfn[N],sz[N]; inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;} inline void dfs0(int x,int fa) { dep[x]=dep[fa]+1,f[x][0]=fa,sz[x]=1,dfn[x]=++dt; for(int i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs0(e[i].to,x),sz[x]+=sz[e[i].to]; } inline int LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=19;~i;i--) if(dep[y]<=dep[f[x][i]]) x=f[x][i]; for(int i=19;~i;i--) if(f[x][i]^f[y][i]) x=f[x][i],y=f[y][i]; return x^y?f[x][0]:x; } inline int dis(int x,int y) {return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);} inline int tim(int x,int y) {return (dis(x,y)+sp[cl[x]]-1)/sp[cl[x]];} inline void upd(int x,int &a,int b) { if(!x) return;else if(!a||!b) return a=a|b,void(); int d1=tim(a,x),d2=tim(b,x);if(d2<d1||(d1==d2&&cl[a]>cl[b])) a=b; } int main() { read(n);for(int i=1,x,y;i<n;i++) read(x,y),adde(x,y),adde(y,x); for(dfs0(1,0),read(Q);Q--;) { read(K,m),idt=0; for(int i=1,x,w;i<=K;i++) read(x,w),cl[x]=i,sp[i]=w,F[x]=x,id[++idt]=x; for(int i=1,x;i<=m;i++) read(x),id[++idt]=x,qr[i]=x; sort(id+1,id+idt+1,[](int a,int b){return dfn[a]<dfn[b];}); for(int i=idt;i>1;i--) id[++idt]=LCA(id[i],id[i-1]); sort(id+1,id+idt+1,[](int a,int b){return dfn[a]<dfn[b];}); idt=unique(id+1,id+idt+1)-id-1,tp=0; for(int i=1;i<=idt;st[++tp]=id[i],i++) { while(tp&&dfn[st[tp]]+sz[st[tp]]<=dfn[id[i]]) tp--; if(tp) fa[id[i]]=st[tp]; } //for(int i=1;i<=idt;i++) printf("%d%c",id[i],i==idt?'\n':' '); for(int i=idt;i>=2;i--) upd(fa[id[i]],F[fa[id[i]]],F[id[i]]); //for(int i=1;i<=idt;i++) printf("%d%c",F[id[i]],i==idt?'\n':' '); for(int i=2;i<=idt;i++) upd(id[i],F[id[i]],F[fa[id[i]]]); for(int i=1;i<=m;i++) printf("%d%c",cl[F[qr[i]]],i==m?'\n':' '); for(int i=1;i<=idt;i++) F[id[i]]=cl[id[i]]=fa[id[i]]=0,id[i]=0; }return 0; }