zoukankan      html  css  js  c++  java
  • CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    一棵根为1 的树,每条边上有一个字符(a-v共22种)。 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中最长的Dokhtar-kosh路径的长度。

    如果重排后能构成回文串,那么出现奇数次的字符最多一个。用一个22位二进制数表示每一个字母出现的次数的奇偶,把一个点到根节点的路径的异或值记为$s[u]$,那么就是在子树里找到两个点使其$s$值异或之后1的个数不超过1个,那么用dsu on tree就可以了

    记得最后别忘了用儿子的答案更新自己的

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #define inf -0x3f3f3f3f
     6 using namespace std;
     7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     8 char buf[1<<21],*p1=buf,*p2=buf;
     9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    10 int read(){
    11     #define num ch-'0'
    12     char ch;bool flag=0;int res;
    13     while(!isdigit(ch=getc()))
    14     (ch=='-')&&(flag=true);
    15     for(res=num;isdigit(ch=getc());res=res*10+num);
    16     (flag)&&(res=-res);
    17     #undef num
    18     return res;
    19 }
    20 inline char getch(){
    21     char ch;while((ch=getc())>'z'||ch<'a');return ch;
    22 }
    23 char sr[1<<21],z[20];int C=-1,Z;
    24 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    25 void print(int x){
    26     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    27     while(z[++Z]=x%10+48,x/=10);
    28     while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    29 }
    30 const int N=5e5+5;
    31 int head[N],Next[N<<1],ver[N<<1],tot;
    32 inline void add(int u,int v){
    33     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    34 }
    35 int sz[N],d[N],son[N],s[N],ans[N],f[N*20],a[N];char c[N];
    36 int mx,n,bin[30];
    37 void dfs1(int u,int fa){
    38     sz[u]=1,d[u]=d[fa]+1,s[u]=s[fa]^bin[a[u]];
    39     for(int i=head[u];i;i=Next[i]){
    40         int v=ver[i];dfs1(v,u);
    41         sz[u]+=sz[v];
    42         if(sz[son[u]]<sz[v]) son[u]=v;
    43     }
    44 }
    45 void calc(int rt,int u){
    46     int now=s[u];cmax(mx,f[now]+d[u]-2*d[rt]);
    47     if((s[u]^s[rt])==0) cmax(mx,d[u]-d[rt]);
    48     for(int i=0;i<22;++i){
    49         now=bin[i]^s[u];
    50         cmax(mx,f[now]+d[u]-2*d[rt]);
    51         if((s[u]^s[rt])==bin[i]) cmax(mx,d[u]-d[rt]);
    52     }
    53     for(int i=head[u];i;i=Next[i]) calc(rt,ver[i]);
    54 }
    55 void update(int u,int k){
    56     k?cmax(f[s[u]],d[u]):f[s[u]]=inf;
    57     for(int i=head[u];i;i=Next[i]) update(ver[i],k);
    58 }
    59 void dfs2(int u,int k){
    60     for(int i=head[u];i;i=Next[i])
    61     if(ver[i]!=son[u]) dfs2(ver[i],0);
    62     if(son[u]) dfs2(son[u],1);
    63     mx=0;int now=s[u];
    64     cmax(mx,f[now]-d[u]);
    65     for(int i=0;i<22;++i)
    66     now=bin[i]^s[u],cmax(mx,f[now]-d[u]);
    67     for(int i=head[u];i;i=Next[i])
    68     if(ver[i]!=son[u]) calc(u,ver[i]),update(ver[i],1);
    69     ans[u]=mx;
    70     if(!k){
    71         for(int i=head[u];i;i=Next[i]) update(ver[i],0);
    72         f[s[u]]=inf;
    73     }else cmax(f[s[u]],d[u]);
    74 }
    75 void spread(int u){
    76     for(int i=head[u];i;i=Next[i]){
    77         int v=ver[i];spread(v);
    78         cmax(ans[u],ans[v]);
    79     }
    80 }
    81 int main(){
    82 //    freopen("testdata.in","r",stdin);
    83     n=read();
    84     bin[0]=1;for(int i=1;i<=25;++i) bin[i]=bin[i-1]<<1;
    85     for(int i=2;i<=n;++i){
    86         int u=read();c[i]=getch();
    87         add(u,i),a[i]=c[i]-'a';
    88     }
    89     dfs1(1,0);
    90     memset(f,0xef,sizeof(f));
    91     dfs2(1,0);spread(1);
    92     for(int i=1;i<=n;++i) print(ans[i]);
    93     return Ot(),0;
    94 }
  • 相关阅读:
    建持续集成
    Apache通用日志工具commonslogging和Log4j使用总结
    subversion(SVN)常见问题及其解决方法
    UML类图的相关名词解释
    SVN项目的目录布局
    敏捷开发流程总结
    敏捷开发实践
    卓有成效的敏捷开发流程
    字符串反转操作
    转:图片水印 http://www.cnblogs.com/xiaoge_com/archive/2009/09/10/1564216.html
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9817996.html
Copyright © 2011-2022 走看看