CodeForces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(思维+dsu on tree+前缀异或)

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

大概是dsu on tree的最难题了吧...还是存在有些地方没有想通。暂时先存下来。

讲的比较详细的思路:这里

Soution:
 注意到字母最大是v,即最多有22种字符,看到这个数据范围就想到利用状压。那么在这题怎么用上状压呢?想到一个性质:一个简单路径可以通过打乱变成回文串,当且仅当在这个路径上出现的次数为奇数的字符个数不超过一个。
 我们状压记录每个字符出现的奇偶性,偶数为0,奇数为1,那么对于以x xx为根的子树中,记s t a p sta_pstap​为p点到x的路径状态,s t a q sta_qstaq​为q点到x的路径状态,那么显然这个总路径的状态就是s t a p sta_pstap​ ^ s t a q sta_qstaq​,暂记为r e t retret,显然路径合法的条件是:r e t retret中1的个数 ≤ 1 \leq 1≤1。
 知道了如何记录,先考虑暴力求解。
s u b t a s k 1 : subtask_1:subtask1​:从根节点x开始搜索,记录所有路径的状态,如何找到这个状态是否和其他链异或起来有合法解?其实也简单,考虑到异或性质的特殊性,即x ^ y = z,则x ^ z = y.那么把当前的路径状态和所有的合法状态(显然只有23种)异或一下,结果暂记为n o w nownow,再查找是否有n o w nownow这个状态就行了。
s u b t a s k 2 : subtask_2:subtask2​:如何得出答案?先求出所有节点的深度,记为d e p i dep_idepi​,那么对于上述的合法状态,答案就是d e p p + d e p q − 2 ∗ d e p x dep_p + dep_q - 2 * dep_xdepp​+depq​−2∗depx​,可以看出d e p p dep_pdepp​和d e p q dep_qdepq​越大越好,所以对于有相同状态的路径,只需要记录深度最深的那个就行了,这样复杂度也有保证。
 上述的暴力求解因为每次要清空状态数组重新记录,复杂度O ( 23 ∗ n 2 ) O(23 * n^2)O(23∗n2),无法通过,想到树的特殊性,题目又是静态的没有修改,加入树上启发式合并,复杂度降为O ( 23 ∗ n ∗ l o g 2 n ) O(23 * n * log_2n)O(23∗n∗log2​n),就可以通过啦。

代码得思考一下怎么写。

讲真这个内部的路径处理问题感觉我想的还不是很通透,就不误人子弟了。待我复习

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<unordered_map>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=5e5+1000;
typedef int LL;
LL siz[maxn],son[maxn],dep[maxn],flag=0;
LL xor_sum[maxn];
LL cnt[1<<22];
LL ans[maxn];
vector< pair<LL,LL> >g[maxn];
void predfs(LL u,LL fa){
    siz[u]=1;dep[u]=dep[fa]+1;
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i].first;
        LL k=g[u][i].second;
        if(v==fa) continue;
        xor_sum[v]=xor_sum[u]^k;///前缀异或,类似前缀和
        predfs(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]]){
            son[u]=v;
        }
    }
}
void cal(LL u,LL fa,LL lca,LL val){

        if(cnt[xor_sum[u]]) ans[lca]=max(ans[lca],cnt[xor_sum[u]]+dep[u]-2*dep[lca]);///枚举的根节点作为lca时候的贡献

        for(LL i=0;i<=21;i++) if(cnt[xor_sum[u]^(1<<i)]) ans[lca]=max(ans[lca],cnt[xor_sum[u]^(1<<i)]+dep[u]-2*dep[lca]);
       /// cnt[xor_sum[u]]=max(cnt[xor_sum[u]],dep[u]);
        for(LL i=0;i<g[u].size();i++){
            LL v=g[u][i].first;
            if(v==fa||v==flag) continue;
            cal(v,u,lca,val);
        }
}
void add(LL u,LL fa,LL val){
     cnt[xor_sum[u]]=max(cnt[xor_sum[u]],dep[u]);
     for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i].first;
        if(v==fa||v==flag) continue;
        add(v,u,val);
     }
}
void del(LL u,LL fa,LL val){
     cnt[xor_sum[u]]=0;
     for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i].first;
        if(v==fa||v==flag) continue;
        del(v,u,val);
     }
}
void dfs(LL u,LL fa,bool keep)
{
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i].first;
        if(v==fa||v==son[u]) continue;
        dfs(v,u,0);
        ans[u]=max(ans[u],ans[v]);///来自不经过u点的轻儿子的最大值转移
    }
    if(son[u]){
        dfs(son[u],u,1);
        flag=son[u];
        ans[u]=max(ans[u],ans[son[u]]);///来自不经过u点的重儿子的最大值转移
    }
    cnt[xor_sum[u]]=max(cnt[xor_sum[u]],dep[u]);///维护相同状态的路径,只需要记录深度最深的那个
    ans[u]=max(ans[u],cnt[xor_sum[u]]-dep[u]);///维护一端连着u,一端在u的子树的内部的链子转移
    for(LL i=0;i<=21;i++) if(cnt[xor_sum[u]^(1<<i)]) ans[u]=max(ans[u],cnt[xor_sum[u]^(1<<i)]-dep[u]);
    for(LL i=0;i<g[u].size();i++){
        LL v=g[u][i].first;
        if(v==fa||v==flag) continue;
        cal(v,u,u,1);
        add(v,u,1);
    }
   /// cal(u,fa,u,1);
   /// add(u,fa,1);
    ///先计算答案,再更新cnt[]
    flag=0;
    if(keep==0){
        del(u,fa,-1);
    }
}
int main(void)
{
  ///cin.tie(0);std::ios::sync_with_stdio(false);
  ///题目以1为根
  LL n;scanf("%d",&n);

  for(LL i=2;i<=n;i++){
     LL x;char str;scanf("%d %c",&x,&str);
     g[x].push_back({i,(1<<(str-'a'))});
     g[i].push_back({x,(1<<(str-'a'))});
  }
  predfs(1,0);
  dfs(1,0,0);
  for(LL i=1;i<=n;i++){
    printf("%d ",ans[i]);
  }
  printf("\n");
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/110581783