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

    题目大意:

      给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长

    解题思路:

      假定给你一个字符串,如何判定其经打乱能否形成回文串,那就是说所有字符中最多只有一个能出现奇数次,22个字符,可以用2进制表示每个字符出现的次数奇偶性,1为奇0为偶,那么处理出一个点到根节点路径上的异或和(设为xi),如果两个节点i,j的xi=xj那么就说明这两个点的路径上符合要求。

      暴力的思路:暴力搜索一棵树中所有的xi看看有没有相同或差一位的再进行答案更新。

      考虑优化,既然是不同子树中的点,那么就可以用一个数组存起来异或和为x的最大深度maxdeep[x],每次进去找,找完再把整颗子树推进去。这样就是O(n2)

      这样就可以用DSU了,每次处理子树时,最后处理重儿子,非重儿子直接推倒,在更新上层时直接在重儿子版本上构建数组,再重建轻儿子,注意更新答案时要更新为子树最大值,跨字数最大值,返祖链最大值中的最大值。时间复杂度O(nlogn)

      DSU还是十分优秀啊

      代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 struct pnt{
      5     int hd;
      6     int dp;
      7     int wgt;
      8     int mxs;
      9     int ans;
     10     int xr;
     11 }p[1000000];
     12 struct ent{
     13     int twd;
     14     int lst;
     15     int vls;
     16 }e[1000000];
     17 int n;
     18 int cnt;
     19 char cmd[100];
     20 int mxdp[10000000];
     21 void ade(int f,int t,int v)
     22 {
     23     cnt++;
     24     e[cnt].twd=t;
     25     e[cnt].lst=p[f].hd;
     26     e[cnt].vls=v;
     27     p[f].hd=cnt;
     28 }
     29 void Basic_dfs(int x,int f)
     30 {
     31     p[x].dp=p[f].dp+1;
     32     p[x].wgt=1;
     33     int maxs=-1;
     34     for(int i=p[x].hd;i;i=e[i].lst)
     35     {
     36         int to=e[i].twd;
     37         p[to].xr=p[x].xr^e[i].vls;
     38         Basic_dfs(to,x);
     39         p[x].wgt+=p[to].wgt;
     40         if(maxs<p[to].wgt)
     41         {
     42             maxs=p[to].wgt;
     43             p[x].mxs=to;
     44         }
     45     }
     46 }
     47 void Build_dfs(int x)
     48 {
     49     mxdp[p[x].xr]=std::max(mxdp[p[x].xr],p[x].dp);
     50     for(int i=p[x].hd;i;i=e[i].lst)
     51         Build_dfs(e[i].twd);
     52 }
     53 void Destory_dfs(int x)
     54 {
     55     mxdp[p[x].xr]=0;
     56     for(int i=p[x].hd;i;i=e[i].lst)
     57         Destory_dfs(e[i].twd);
     58 }
     59 void Ans_dfs(int x,int a)
     60 {
     61     if(mxdp[p[x].xr])
     62         p[a].ans=std::max(p[a].ans,p[x].dp+mxdp[p[x].xr]-2*p[a].dp);
     63     for(int i=0;i<22;i++)
     64     {
     65         int tmp=1<<i;
     66         if(mxdp[p[x].xr^tmp])
     67             p[a].ans=std::max(p[a].ans,p[x].dp+mxdp[p[x].xr^tmp]-2*p[a].dp);
     68     }
     69     for(int i=p[x].hd;i;i=e[i].lst)
     70         Ans_dfs(e[i].twd,a);
     71 }
     72 void DSU_dfs(int x,bool hvs)
     73 {
     74     for(int i=p[x].hd;i;i=e[i].lst)
     75     {
     76         int to=e[i].twd;
     77         if(to==p[x].mxs)
     78             continue;
     79         DSU_dfs(to,false);
     80         p[x].ans=std::max(p[x].ans,p[to].ans);
     81     }
     82     if(p[x].mxs)
     83     {
     84         DSU_dfs(p[x].mxs,true);
     85         p[x].ans=std::max(p[x].ans,p[p[x].mxs].ans);
     86     }
     87     if(mxdp[p[x].xr])
     88         p[x].ans=std::max(p[x].ans,mxdp[p[x].xr]-p[x].dp);
     89     for(int i=0;i<22;i++)
     90     {
     91         int tmp=1<<i;
     92         if(mxdp[p[x].xr^tmp])
     93             p[x].ans=std::max(p[x].ans,mxdp[p[x].xr^tmp]-p[x].dp);
     94     }
     95     mxdp[p[x].xr]=std::max(p[x].dp,mxdp[p[x].xr]);
     96     for(int i=p[x].hd;i;i=e[i].lst)
     97     {
     98         int to=e[i].twd;
     99         if(to==p[x].mxs)
    100             continue;
    101         Ans_dfs(to,x);
    102         Build_dfs(to);
    103     }
    104     if(hvs)
    105         return ;
    106     Destory_dfs(x);
    107 }
    108 int main()
    109 {
    110     scanf("%d",&n);
    111     for(int i=2;i<=n;i++)
    112     {
    113         int x;
    114         scanf("%d",&x);
    115         scanf("%s",cmd);
    116         int tmp=1<<(cmd[0]-'a');
    117         ade(x,i,tmp);
    118     }
    119     Basic_dfs(1,1);
    120     DSU_dfs(1,true);
    121     for(int i=1;i<=n;i++)
    122         printf("%d ",p[i].ans);
    123     puts("");
    124     return 0;
    125 }
  • 相关阅读:
    db.Exec和db.Query的区别
    golang两种get请求获取携带参数的方式
    gin实现中间件middleware
    gin操作session
    笔札-有触动的句子
    并发的基本概念
    售货员的难题
    传球游戏之最小总代价
    状压dp入门
    [COCI 2010] OGRADA
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9563432.html
Copyright © 2011-2022 走看看