[CF741D] Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

又是玄学的dsu on tree ,这次还用到了二进制状压的思想......

用二进制压一个x表示根到节点的链上的字符信息,奇数个为1,偶数个为0。

那么如果x的二进制表示里有不多于一个1,那么重排后就能形成回文串啦。

对于两条链,如果想合并信息,异或一下就OK。

这个题很难想啊......

简单地说,就是子树里乱搞啦~哈哈哈~

然后用dsu on tree搞一下,据说用(dfs序+for循环)代替(dfs深搜子树),能大幅优化常数。

题目传送门

其实思路也不是很烧脑,盯着代码想一想就差不多了吧。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define maxn 500005
 5 using namespace std;
 6 
 7 int n;
 8 int hd[maxn],nx[maxn<<1],to[maxn<<1],c[maxn<<1],cnt;
 9 int sz[maxn],dep[maxn],x[maxn],f[1<<23],ans[maxn];
10 int st[maxn],ed[maxn],fnd[maxn],ord;
11 
12 void edge(int af,int at,int ac)
13 {
14     to[++cnt]=at;
15     c[cnt]=ac;
16     nx[cnt]=hd[af];
17     hd[af]=cnt;
18 }
19 
20 void pre(int p,int fa,int ec)
21 {
22     st[p]=++ord;
23     fnd[ord]=p;
24     sz[p]=1;
25     dep[p]=dep[fa]+1;
26     x[p]=(x[fa]^(1<<ec));
27     for(int i=hd[p];i;i=nx[i])
28     {
29         if(to[i]==fa)continue;
30         pre(to[i],p,c[i]);
31         sz[p]+=sz[to[i]];
32     }
33     ed[p]=ord;
34 }
35 
36 void dfs(int p,int fa,int stay)
37 {
38     int son=0,mx=-1;
39     for(int i=hd[p];i;i=nx[i])
40     {
41         if(to[i]==fa)continue;
42         if(sz[to[i]]>mx)mx=sz[to[i]],son=to[i];
43     }
44     for(int i=hd[p];i;i=nx[i])
45     {
46         if(to[i]==fa||to[i]==son)continue;
47         dfs(to[i],p,0);
48         ans[p]=max(ans[p],ans[to[i]]);
49     }
50     if(son)dfs(son,p,1),ans[p]=max(ans[p],ans[son]);
51     if(f[x[p]])ans[p]=max(ans[p],f[x[p]]-dep[p]);
52     for(int i=0;i<22;i++)
53         if(f[x[p]^(1<<i)])
54             ans[p]=max(ans[p],f[x[p]^(1<<i)]-dep[p]);
55     f[x[p]]=max(f[x[p]],dep[p]);
56     for(int i=hd[p];i;i=nx[i])
57     {
58         if(to[i]==fa||to[i]==son)continue;
59         for(int j=st[to[i]];j<=ed[to[i]];j++)
60         {
61             if(f[x[fnd[j]]])
62                 ans[p]=max(ans[p],f[x[fnd[j]]]+dep[fnd[j]]-2*dep[p]);
63             for(int k=0;k<22;k++)
64             {
65                 if(f[x[fnd[j]]^(1<<k)])
66                     ans[p]=max(ans[p],f[x[fnd[j]]^(1<<k)]+dep[fnd[j]]-2*dep[p]);
67             }
68         }
69         for(int j=st[to[i]];j<=ed[to[i]];j++)
70         {
71             f[x[fnd[j]]]=max(f[x[fnd[j]]],dep[fnd[j]]);
72         }
73     }
74     if(!stay)for(int i=st[p];i<=ed[p];i++)f[x[fnd[i]]]=0;
75 }
76 
77 int main()
78 {
79     scanf("%d",&n);
80     for(int i=2;i<=n;i++)
81     {
82         int t;
83         char s[5];
84         scanf("%d",&t);
85         scanf("%s",s+1);
86         edge(i,t,s[1]-'a');
87         edge(t,i,s[1]-'a');
88     }
89     pre(1,0,0);
90     dfs(1,0,1);
91     for(int i=1;i<=n;i++)printf("%d ",ans[i]);
92     return 0;
93 }
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
原文地址:https://www.cnblogs.com/cervusy/p/9562595.html