zoukankan      html  css  js  c++  java
  • [luogu6702]Path

    维护每一个点到根路径的异或和(记作$d_{k}$),根据异或自反性,$(x,y)$的异或和即$d_{x}oplus d_{y}$

    考虑两条路径的lca,选择其中深度较大的点,另一条路径必然在其子树外,枚举这个点,分别统计子树内外异或和最大的路径

    对于子树内,用启发式合并trie树,在合并时顺便统计出答案(枚举较小的一棵trie树中的点,在另一颗trie树中查询),时间复杂度为$o(nlog_{2}nlog_{2}w)$

    对于子树外,任选一条全局异或和最大的路径$(p,q)$,然后将其以$p$为根建树(子树内也需要以$p$为根考虑)

    将所有点分为两类:1.子树内不含有$q$;2.子树内含有$q$,对于前者必然选择$(p,q)$这条路径,否则也就是从$p$递归到$q$为止的时候

    此时,暴力合并子树外的节点(即父亲子树外的节点与父亲子树内除自己外的节点),不难发现每一个节点至多合并一次,暴力合并即可做到$o(nlog_{2}w)$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 30005
      4 int E,n,x,y,z,mx,now_mx,ans,head[N],d[N],vis[N],f[N];
      5 struct ji{
      6     int nex,to,len;
      7 }edge[N<<1];
      8 struct trie{
      9     int V;
     10     vector<int>v,ch[2];
     11     void New(){
     12         ch[0].push_back(-1);
     13         ch[1].push_back(-1);
     14         V++;
     15     }
     16     void init(){
     17         V=0;
     18         v.clear(),ch[0].clear(),ch[1].clear();
     19         New();
     20     }
     21     void add(int x){
     22         v.push_back(x);
     23         int k=0;
     24         for(int i=29;i>=0;i--){
     25             int p=((x&(1<<i))>0);
     26             if (ch[p][k]<0){
     27                 ch[p][k]=V;
     28                 New();
     29                 assert(ch[p][k]>=0);
     30             }
     31             k=ch[p][k];
     32         }
     33     }
     34     int query(int x){
     35         if (!v.size())return 0;
     36         int k=0,ans=0;
     37         for(int i=29;i>=0;i--){
     38             int p=((x&(1<<i))==0);
     39             if (ch[p][k]<0)p^=1;
     40             else ans+=(1<<i);
     41             k=ch[p][k];
     42         }
     43         return ans;
     44     }
     45     int merge(int x){
     46         add(x);
     47         return query(x);
     48     }
     49 }T[N];
     50 int find(int k){
     51     if (k==f[k])return k;
     52     return f[k]=find(f[k]);
     53 }
     54 int merge(int x,int y){
     55     x=find(x),y=find(y);
     56     assert(x!=y);
     57     if (T[x].v.size()<T[y].v.size())swap(x,y);
     58     f[y]=x;
     59     int ans=0;
     60     for(int i=0;i<T[y].v.size();i++)ans=max(ans,T[x].merge(T[y].v[i]));
     61     T[y].init();
     62     return ans;
     63 }
     64 void add(int x,int y,int z){
     65     edge[E].nex=head[x];
     66     edge[E].to=y;
     67     edge[E].len=z;
     68     head[x]=E++;
     69 }
     70 void dfs(int k,int fa,int s){
     71     d[k]=s;
     72     f[k]=fa;
     73     for(int i=head[k];i!=-1;i=edge[i].nex)
     74         if (edge[i].to!=fa)dfs(edge[i].to,k,s^edge[i].len);
     75 }
     76 void tot(int k,int fa){
     77     now_mx=max(now_mx,T[0].merge(d[k]));
     78     for(int i=head[k];i!=-1;i=edge[i].nex)
     79         if (edge[i].to!=fa)tot(edge[i].to,k);
     80 }
     81 void calc(int k,int fa){
     82     int si=T[k].merge(d[k]),so=mx;
     83     if (vis[k]){
     84         so=now_mx;
     85         now_mx=max(now_mx,T[0].merge(d[k]));
     86         for(int i=head[k];i!=-1;i=edge[i].nex)
     87             if (!vis[edge[i].to])tot(edge[i].to,k);
     88     }
     89     for(int i=head[k];i!=-1;i=edge[i].nex)
     90         if (edge[i].to!=fa){
     91             calc(edge[i].to,k);
     92             si=max(si,merge(k,edge[i].to));
     93         }
     94     if (fa)ans=max(ans,si+so);
     95 }
     96 int main(){
     97     scanf("%d",&n);
     98     memset(head,-1,sizeof(head));
     99     for(int i=1;i<n;i++){
    100         scanf("%d%d%d",&x,&y,&z);
    101         add(x,y,z);
    102         add(y,x,z);
    103     }
    104     dfs(1,0,0);
    105     T[0].init();
    106     for(int i=1;i<=n;i++)mx=max(mx,T[0].merge(d[i]));
    107     for(int i=1;i<=n;i++)
    108         if (T[0].query(d[i])==mx){
    109             x=i;
    110             break;
    111         }
    112     for(int i=1;i<=n;i++)
    113         if ((d[x]^d[i])==mx){
    114             y=i;
    115             break;
    116         }
    117     dfs(x,0,0);
    118     while (y){
    119         vis[y]=1;
    120         y=f[y];
    121     }
    122     for(int i=0;i<=n;i++)T[i].init();
    123     for(int i=1;i<=n;i++)f[i]=i;
    124     calc(x,0);
    125     printf("%d",ans);
    126 }
    View Code
  • 相关阅读:
    Git——新手入门与上传项目到远程仓库GitHub
    在树莓派上用Python控制LED
    树莓派从 DHT11 温度湿度传感器读取数据
    树莓派使用DHT11温湿度传感器(C语言程序)
    树莓派使用DHT11温湿度传感器(C语言)
    树莓派连接DHT11温湿度传感器(python)
    教你在树莓派使用上RTC实时时钟,不用再担心断电后时间归零的问题,开机后自动同步RTC时钟!!!
    【手把手教你树莓派3 (一)】装机
    【手把手教你树莓派3 (二)】 启动wifi模块
    Notes on Noise Contrastive Estimation and Negative Sampling
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14303073.html
Copyright © 2011-2022 走看看