P4592 [TJOI2018]异或

吐槽

睡起来写道模板清醒一下
貌似有两个log的树剖写法,还有一个log的Trie树的差分做法(类似于count on a tree),然后一个log的要把两个询问分开写,一个dfs序一个差分,然后我就写了好写的树剖写法
以及为啥出题人这么喜欢把序列问题放到树上啊。。。
可持久化Tried树模板难度,懒得写思路

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100100;
struct Node{
    int son[2],sz;
}Trie[MAXN*40];
const int MAXlen=30;
int u[MAXN<<1],v[MAXN<<1],w[MAXN],nxt[MAXN<<1],root[MAXN],dep[MAXN],fir[MAXN],id[MAXN],top[MAXN],sz[MAXN],heason[MAXN],fa[MAXN],cnt,dfs_clock,w_p[MAXN],n,m,Nodecnt;
void addedge(int ui,int vi){
    ++cnt;
    u[cnt]=ui;
    v[cnt]=vi;
    nxt[cnt]=fir[ui];
    fir[ui]=cnt;
}
void dfs1(int u,int f){
    sz[u]=1;
    fa[u]=f;
    dep[u]=dep[f]+1;
    for(int i=fir[u];i;i=nxt[i]){
        if(v[i]==f)
            continue;
        dfs1(v[i],u);
        sz[u]+=sz[v[i]];
        if(heason[u]==0||sz[heason[u]]<sz[v[i]])
            heason[u]=v[i];
    }
}
void dfs2(int u,int topf){
    id[u]=++dfs_clock;
    w[id[u]]=w_p[u];
    top[u]=topf;
    if(!heason[u])
        return;
    dfs2(heason[u],topf);
    for(int i=fir[u];i;i=nxt[i]){
        if(v[i]==fa[u]||v[i]==heason[u])
            continue;
        dfs2(v[i],v[i]);
    }
}
void insert(int d,int val,int &o){
    Trie[++Nodecnt]=Trie[o];
    o=Nodecnt;
    Trie[o].sz++;
    if(d>=0)
        insert(d-1,val,Trie[o].son[(val>>d)&1]);
}
int query(int lroot,int rroot,int val,int d){
    if(d<0)
        return 0;
    int flag=(val>>d)&1;
    if(Trie[rroot].son[!flag]>Trie[lroot].son[!flag])
        return (1<<d)+query(Trie[lroot].son[!flag],Trie[rroot].son[!flag],val,d-1);
    else
        return query(Trie[lroot].son[flag],Trie[rroot].son[flag],val,d-1);
}
void build(void){
    for(int i=1;i<=dfs_clock;i++){
        root[i]=root[i-1];
        insert(MAXlen,w[i],root[i]);
    }
}
int query(int x,int y,int c){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        ans=max(ans,query(root[id[top[x]]-1],root[id[x]],c,MAXlen));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x,y);
    ans=max(ans,query(root[id[x]-1],root[id[y]],c,MAXlen));
    return ans;
}
int query(int x,int c){
    return query(root[id[x]-1],root[id[x]+sz[x]-1],c,MAXlen);
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&w_p[i]);
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        addedge(a,b);
        addedge(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    build();
    for(int i=1;i<=m;i++){
        int opt,x,y,z;
        scanf("%d %d %d",&opt,&x,&y);
        if(opt==1){
            printf("%d\n",query(x,y));
        }
        else{
            scanf("%d",&z);
            printf("%d\n",query(x,y,z));
        }
    }
    return 0;
}
posted @ 2019-03-09 17:17  dreagonm  阅读(149)  评论(0编辑  收藏  举报