題目鏈接:Russian Dolls on the Christmas Tree
顯然可以dfs序轉區間之後上莫隊,不過感覺會被卡。
其實也可以dfs序之後,對詢問區間排序,然後線段樹。
我懶得dfs序,直接樹上啓發式合併做了。
顯然節點兒子信息是可以繼承的,所以繼承重兒子,暴力輕兒子即可。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,vis[N],res,ans[N],sz[N],son[N],ts;
vector<int> g[N];
inline void add(int a,int b){g[a].push_back(b),g[b].push_back(a);}
void dfs1(int x,int fa){
sz[x]=1;
for(auto to:g[x]) if(to!=fa){
dfs1(to,x); sz[x]+=sz[to];
if(sz[to]>sz[son[x]]) son[x]=to;
}
}
void del(int x,int fa){
vis[x]=0;
if(vis[x-1]&&vis[x+1]) res++;
else if(!vis[x-1]&&!vis[x+1]) res--;
for(auto to:g[x]) if(to!=fa) del(to,x);
}
void insert(int x,int fa){
vis[x]=1;
if(vis[x-1]&&vis[x+1]) res--;
else if(!vis[x-1]&&!vis[x+1]) res++;
for(auto to:g[x]) if(to!=fa) insert(to,x);
}
void dfs2(int x,int fa){
for(auto to:g[x]) if(to!=fa&&to!=son[x]) dfs2(to,x),del(to,x);
if(son[x]) dfs2(son[x],x);
for(auto to:g[x]) if(to!=son[x]&&to!=fa) insert(to,x);
vis[x]=1;
if(vis[x-1]&&vis[x+1]) res--;
else if(!vis[x-1]&&!vis[x+1]) res++;
ans[x]=res;
}
inline void solve(){
cin>>n; res=0;
for(int i=1;i<=n;i++) vis[i]=son[i]=0,g[i].clear();
for(int i=1,a,b;i<n;i++) scanf("%d %d",&a,&b),add(a,b);
dfs1(1,1); dfs2(1,1);
printf("Case #%d: ",++ts);
for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
}
signed main(){
int T; cin>>T; while(T--) solve();
return 0;
}