LOJ10056

13 篇文章 0 订阅
7 篇文章 0 订阅

LOJ10056

实际上,这题只要任选一个根,将无根树转为有根树,构造val[x]表示从根到x节点的异或和,就变成模板LOJ10050
为什么这样是对的?

  • 异或同一个数偶数次等于啥也没干
  • 异或满足交换律( x xor y=y xor x x   x o r   y = y   x o r   x

    所以可以构造“前缀异或”

  • 若(x,y)不在同一条到根的树链上,显然val[x] xor val[y]没问题
    1

  • 若(x,y)各自到根的树链有并链,则
    (val[x] xor val[z])xor(val[y] xor val[z])
    =val[x] xor val[y] xor val[z] xor val[z]
    =val[x] xor val[y]
    2
  • 若(x,y)在同一条到根的树链上,val[x] xor val[y]=val[y] xor val[x]
    3
    然后就好了,复杂度 O(N302) O ( N ∗ 30 ∗ 2 )
#include<bits/stdc++.h>
#define gt() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
#define __R register
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf;
const int maxn=(1e5)+5,L=31;
int n,Ans,val[maxn],Pow[L+5];
int tot,son[maxn<<1],nxt[maxn<<1],lnk[maxn],w[maxn<<1];
void add_e(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
int read(){
    int ret=0;char ch=gt();
    while(ch<'0'||ch>'9') ch=gt();
    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
    return ret;
}
struct Trie{
    int tot,s[maxn*L][3],cnt[maxn*L];
    inline void insert(int x){
        __R int rot=0;__R bool p;
        for(__R int i=L-1;i>=0;i--) rot=s[rot][p=(x>>i)&1]=s[rot][p]?s[rot][p]:++tot;
    }
    inline void check(int x){
        __R int rot1=0,rot2=0,now=0;__R bool p;
        for(__R int i=L-1;i>=0;i--){
            rot1=s[rot1][p=(x>>i)&1];
            if(s[rot2][!p]) now|=Pow[i],rot2=s[rot2][!p];else rot2=s[rot2][p];
            if(now+Pow[i]-1<=Ans) return;
        }
        Ans=now;
    }
}T;
void DFS(int x,int fa){for(__R int j=lnk[x];j;j=nxt[j])if(son[j]!=fa) T.insert(val[son[j]]=val[x]^w[j]),DFS(son[j],x);}
int main(){
    n=read();
    for(__R int i=0;i<L;i++) Pow[i]=1<<i;
    for(__R int i=1;i<n;i++){
        int x=read(),y=read(),z=read();
        add_e(x,y,z),add_e(y,x,z);
    }
    DFS(1,-1);
    for(__R int i=1;i<=n;i++) T.check(val[i]);
    printf("%d\n",Ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值