zoukankan      html  css  js  c++  java
  • 【题解】CF741D(DSU on TREE)

    【题解】CF741D(DSU on TREE)

    写一写这道题来学习学习模板

    用二进制来转换一下条件,现在就是要求一下(lowbit(x)=x)的那些路径了。

    DSU on TREE 是这样一种算法:

    • 像树剖一样分出轻重链,根据那套理论可知轻边(O(log n))
    • 递归处理一个节点的所有轻儿子,并且回溯的时候将统计信息清空。
    • 递归处理一个节点的那个重儿子,并且回溯的时候保留统计信息。
    • 获得重儿子信息后,遍历一下所有轻儿子统计答案。

    分析复杂度:对于每个点,可以被他父亲所有的轻边多遍历一次。复杂度(O(tn log n))(t)是加入一个信息需要的复杂度。

    具体到这道题的话,就是开桶记录该二进制状态下最深深度点的深度。取(max)就好

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    char c;
    const int maxn=5e5+5,inf=1e9;
    int d[maxn],cnt[1<<22|1],n,siz[maxn],son[maxn],dfn[maxn],End[maxn],arc[maxn];
    int ans[maxn],dis[maxn];
    vector< pair<int,int> > e[maxn];
    inline void add(const int&fr,const int&to,const int&w){
          e[fr].push_back({to,1<<w});
    }
    
    void predfs(const int&now){
          siz[now]=1;
          dfn[now]=++*dfn;
          arc[*dfn]=now;
          for(auto t:e[now])
    	    d[t.first]=d[now]^t.second,dis[t.first]=dis[now]+1,predfs(t.first),siz[now]+=siz[t.first],son[now]=siz[t.first]>siz[son[now]]?t.first:son[now];
          End[now]=*dfn;
    }
    
    void dfs(const int&now,const int&keep){
          for(auto t:e[now])
    	    if(t.first^son[now])
    		  dfs(t.first,0),ans[now]=max(ans[now],ans[t.first]);
          if(son[now]) dfs(son[now],1),ans[now]=max(ans[now],ans[son[now]]);
          if(cnt[d[now]]) ans[now]=max(ans[now],cnt[d[now]]-dis[now]);
          for(int t=0;t<22;++t)
    	    if(cnt[d[now]^(1<<t)])
    		  ans[now]=max(ans[now],cnt[d[now]^(1<<t)]-dis[now]);
          cnt[d[now]]=max(cnt[d[now]],dis[now]);
          for(auto T:e[now])
    	    if(T.first^son[now]){
    		  for(int t=dfn[T.first];t<=End[T.first];++t){
    			if(cnt[d[arc[t]]])
    			      ans[now]=max(ans[now],cnt[d[arc[t]]]+dis[arc[t]]-dis[now]*2);
    			for(int i=0;i<22;++i)
    			      if(cnt[d[arc[t]]^(1<<i)])
    				    ans[now]=max(ans[now],cnt[d[arc[t]]^(1<<i)]+dis[arc[t]]-dis[now]*2);
    		  }
    		  for(int t=dfn[T.first];t<=End[T.first];++t)
    			cnt[d[arc[t]]]=max(cnt[d[arc[t]]],dis[arc[t]]);
    	    }
          if(!keep) for(int t=dfn[now];t<=End[now];++t) cnt[d[arc[t]]]=0;
    }
    
    int main(){
          n=qr();
          for(int t=2,t1;t<=n;++t){
    	    t1=qr();
    	    char c=getchar();
    	    while(c<'a'||c>'z') c=getchar();
    	    add(t1,t,c-'a');
          }
          predfs(1);
          dfs(1,0);
          for(int t=1;t<=n;++t) printf("%d ",ans[t]);
          putchar('
    ');
          return 0;
    }
    
    
  • 相关阅读:
    GO语言网络编程
    GO语言测试
    GO语言反射
    GO语言strconv包的使用
    GO语言并发
    Centos7 开启swap分区
    设计模式 之 命令模式
    设计模式 之 代理模式
    设计模式 之 工厂模式
    设计模式 之 观察者模式
  • 原文地址:https://www.cnblogs.com/winlere/p/11546020.html
Copyright © 2011-2022 走看看