HDU 4757 可持久化trie树

思路:
可持久化trie树裸题
x->y 就是x +y -lca(x,y) -fa[lca(x,y)]
学了可持久化线段树 再看这个就无压力了

注意是多组数据……

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100050
#define mem(x,y) memset(x,y,sizeof(x))
int first[N],nxt[N*2],v[N*2],w[N*2],tot,xx,yy,zz,n,m;
int size[N],son[N],fa[N],top[N],deep[N],a[N];
int cnt,ch[N*20][2],wei[N*20],f,root[N];
void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
void insert(int last,int num){
    int now=cnt;
    for(int i=16;i>=0;i--){
        f=num&(1<<i)?1:0;
        ch[now][f]=++cnt;ch[now][!f]=ch[last][!f];
        last=ch[last][f],now=ch[now][f];
        wei[now]=wei[last]+1;
    }
}
void dfs(int x){
    size[x]=1,son[x]=0;root[x]=++cnt,insert(root[fa[x]],a[x]);
    for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x]){
        fa[v[i]]=x,deep[v[i]]=deep[x]+1,dfs(v[i]);
        size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
    }
}
void dfs2(int x,int tp){
    top[x]=tp;
    if(son[x])dfs2(son[x],tp);
    for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x]&&v[i]!=son[x])
        dfs2(v[i],v[i]);
}
int lca(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
        x=fa[fx],fx=top[x];
    }return deep[x]<deep[y]?x:y;
}
int query(int x,int y,int lca,int flca,int num){
    int temp=0;
    for(int i=16;i>=0;i--){
        f=num&(1<<i)?0:1;
        if(wei[ch[x][f]]+wei[ch[y][f]]-wei[ch[lca][f]]-wei[ch[flca][f]]>0)
            x=ch[x][f],y=ch[y][f],lca=ch[lca][f],flca=ch[flca][f],temp+=(1<<i);
        else x=ch[x][!f],y=ch[y][!f],lca=ch[lca][!f],flca=ch[flca][!f];
    }return temp;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        mem(first,-1),tot=cnt=0;
        mem(ch,0),mem(wei,0);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<n;i++){
            scanf("%d%d",&xx,&yy);
            add(xx,yy),add(yy,xx);
        }
        dfs(1),dfs2(1,1);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&xx,&yy,&zz);
            int LCA=lca(xx,yy);
            printf("%d\n",query(root[xx],root[yy],root[LCA],root[fa[LCA]],zz));
        }
    }
}

这里写图片描述

附一个小小的对拍:

maker:

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
int seed,n,m;
int main(){
    freopen("seed.txt","r",stdin);
    scanf("%d",&seed);
    srand(seed+time(0));rand();rand();rand();rand();rand();
    freopen("seed.txt","w",stdout);
    printf("%d\n",rand());
    freopen("in.txt","w",stdout);
    int cases=5;
    while(cases--){
        n=rand()%100000+1,m=rand()%100000+1;
        printf("%d %d\n",n,m);
        for(int i=1;i<=n;i++)printf("%d ",rand()%65536);
        for(int i=2;i<=n;i++)printf("%d %d\n",i,rand()%(i-1)+1);
        for(int i=1;i<=m;i++){
            printf("%d %d %d\n",rand()%n+1,rand()%n+1,rand()%65536);
        }
    }
}

pai:

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
long int bt,cases;
int main(){
    while(1){
        bt=clock();
        printf("Case %ld\n",++cases);
        system("mk.exe");
        printf("maker time =%ldms\n",clock()-bt);
        bt=clock();
        system("a.exe<in.txt>out1.txt");
        printf("time a =%ldms\n",clock()-bt);
        bt=clock();
        system("b.exe<in.txt>out2.txt");
        printf("time b =%ldms\n",clock()-bt);
        if(system("fc out1.txt out2.txt")){
            puts("Wrong Answer~~~");
            while(1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值