QTREE6 - Query on a tree VI 解題報告
阿新 • • 發佈:2018-12-08
QTREE6 - Query on a tree VI
題目描述
給你一棵\(n\)個點的樹,編號\(1\)~\(n\)。每個點可以是黑色,可以是白色。初始時所有點都是黑色。下面有兩種操作請你操作給我們看:
0 u:詢問有多少個節點v滿足路徑u到v上所有節點(包括)都擁有相同的顏色
1 u:翻轉u的顏色
輸入格式
一行一個整數\(n\)
接下來\(n-1\)行,每行兩個整數表示一條邊
接下來一行一個整數\(m\)表示操作次數
接下來\(m\)行,每行兩個整數分別表示操作型別和被操作節點
輸出格式
對每個詢問操作輸出相應的結果
暴力分兩棵樹LCT維護會菊花樹卡。
考慮把點權放到邊上,這樣的好處是當維護聯通性時,只會改一條邊。
把樹搞成兩顆,分別用LCT維護,一個點在啟用在對應顏色的樹的頭頂邊。
我們要資瓷詢問子樹資訊,維護方法可以先做“大融合”
然後發現為了維護樹的形態,我們不可以進行換根。
那麼就要根據修改的形式自己yy\(link,cat,qurey\)那些東西了。
Code:
#include <cstdio> #include <cstring> const int N=502; int head[N],to[N<<1],Next[N<<1],cnt; void add(int u,int v) { to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt; } int dp[N][2]; int max(int x,int y){return x>y?x:y;} void dfs(int now,int fa,int da,int db) { int s1=0,s2=-N,ison=0; for(int v,i=head[now];i;i=Next[i]) if((v=to[i])!=fa) { dfs(v,now,da,db); s1+=max(dp[v][0],dp[v][1]); ison=1; } for(int v,i=head[now];i;i=Next[i]) if((v=to[i])!=fa) s2=max(s2,s1-max(dp[v][0],dp[v][1])+dp[v][0]); dp[now][0]=s1,dp[now][1]=s2+ison; if(now==da||now==db) dp[now][1]=dp[now][0],dp[now][0]=-N; } int cal(int a,int b) { memset(dp,0,sizeof(dp)); dfs(1,0,a,b); return max(dp[1][0],dp[1][1])+(a>0); } int n; int main() { scanf("%d",&n); for(int u,v,i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v),add(v,u); } int a=cal(0,0),ans=0; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { int d=cal(i,j); if(d==a+1) ++ans; } printf("%d\n",ans); return 0; }
2018.12.8