1. 程式人生 > >cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

-m bool problem 排列 code ++ void col i++

題目鏈接:Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

  第一次寫\(dsu\ on\ tree\),來記錄一下

  \(dsu\ on\ tree\)主要維護子樹信息,往往可以省掉一個數據結構的啟發式合並。大體思路如下:

  輕重鏈路徑剖分之後,對每個點先遞歸處理他的所有輕兒子,每次處理完輕兒子之後把這棵子樹的信息清空。最後再來處理重孩子,重兒子的信息就可以不用清空了。由於我們是用一個全局數組來記錄信息的,重兒子子樹的信息就仍然保留在全局數組中。接著我們另外寫一個函數\(dfs\)所有的輕兒子子樹,並統計答案。每統計完一棵子樹的答案就可以把這棵子樹的信息計入全局數組中,用於下一次更新。由於每個點到根的輕邊條數是\(\log n\)級別的,所以每個點最多被掃\(\log n\)遍。

  回到這道題上來。由於要求路徑上的所有字符重新排列之後可以形成一個回文串,也就是說出現次數為奇數的字符不會超過\(1\)個。那麽我們就可以給每個字符一個\(2^x\)形式的權值,這樣的話合法路徑的異或和要麽為\(0\),要麽為\(2^x\)的形式。

  設點\(x\)到根的異或和為\(D_x\),由於這道題是邊權,\(x\)和\(y\)路徑上的異或和就可以用\(D_x\ xor\ D_y\)來表示。這樣的話就可以用一個數組\(c\)來統計答案,其中\(c_i\)表示滿足\(D_x=i\)的\(x\)的最大深度。剩下的就是套\(dsu\ on\ tree\)的板子了。

  下面貼代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 500010
#define INF (1<<30)

using namespace std;
typedef long long llg;

int n,ci[1<<22],son[maxn],siz[maxn],dep[maxn];
int hd[maxn],nt[maxn],D[maxn],ans[maxn];

int getint(){
	int w=0;bool q=0;
	char c=getchar();
	while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar();
	if(c==‘-‘) c=getchar(),q=1;
	while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar();
	return q?-w:w;
}

void dfs(int u){
	siz[u]=1;
	for(int i=hd[u];i;i=nt[i]){
		D[i]^=D[u]; dep[i]=dep[u]+1;
		dfs(i); siz[u]+=siz[i];
		if(siz[i]>siz[son[u]]) son[u]=i;
	}
}

void undo(int u){
	ci[D[u]]=-INF;
	for(int i=hd[u];i;i=nt[i]) undo(i);
}

int o;
void up(int &x,int y){if(y>x) x=y;}
void up(int u){
	up(ans[o],dep[u]+ci[D[u]]);
	for(int i=0;i<=21;i++) up(ans[o],dep[u]+ci[1<<i^D[u]]);
	for(int i=hd[u];i;i=nt[i]) up(i);
}

void ins(int u){
	up(ci[D[u]],dep[u]);
	for(int i=hd[u];i;i=nt[i]) ins(i);
}

void work(int u){
	for(int i=hd[u];i;i=nt[i])
		if(i!=son[u]) work(i),undo(i);
	if(son[u]) work(son[u]); o=u;
	for(int i=hd[u];i;i=nt[i])
		if(i!=son[u]) up(i),ins(i);
	up(ci[D[u]],dep[u]);
	up(ans[u],dep[u]+ci[D[u]]);
	for(int i=0;i<=21;i++) up(ans[u],dep[u]+ci[1<<i^D[u]]);
	ans[u]-=dep[u]<<1;
	for(int i=hd[u];i;i=nt[i]) up(ans[u],ans[i]);
}

int main(){
	File("a");
	n=getint();
	for(int i=0;i<(1<<22);i++) ci[i]=-INF;
	for(int i=2,x;i<=n;i++){
		x=getint();
		nt[i]=hd[x];hd[x]=i;
		char c=getchar();
		while(c>‘v‘ || c<‘a‘) c=getchar();
		D[i]=1<<(c-‘a‘);
	}
	dfs(1); work(1);
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
	return 0;
}

cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths