bzoj 5338: [TJOI2018]xor (树链剖分+可持久化01Trie)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5338

题面:

5338: [TJOI2018]xor

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 269  Solved: 171
[Submit][Status][Discuss]

Description

现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi。
现在有Q 次操作,操作如下:
1  x y    查询节点x的子树中与y异或结果的最大值
2 x y z    查询路径x到y上点与z异或结果最大值
 

 

Input

第一行是两个数字n, Q;
第二行是n个数字用空格隔开,第i个数字vi表示点i上的权值 
接下来n-1行,每行两个数,x,y,表示节点x与y之间有边 
接下来Q行,每一行为一个查询,格式如上所述.
1 < n, Q ≤ 100000 ,查询1中的y ≤ 2^30 ,查询2中的z ≤ 2^30
 

 

Output

对于每一个查询,输出一行,表示满足条件的最大值。
 

 

Sample Input

7 5
1 3 5 7 9 2 4
1 2
1 3
2 4
2 5
3 6
3 7
1 3 5
2 4 6 3
1 5 5
2 5 7 2
1 1 9

Sample Output

7
6
12
11
14
 
实现代码;
#include<bits/stdc++.h>
using namespace std;
const int M = 2e5+10;
struct node{
    int to,next;
}e[M];
int cnt,cnt1,n;
int son[M],siz[M],head[M],fa[M],top[M],dep[M],tid[M],mx[M],rk[M];
void add(int u,int v){
    e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
}

void dfs1(int u,int faz,int deep){
    dep[u] = deep;
    fa[u] = faz;
    siz[u] = 1;
    for(int i = head[u];i;i = e[i].next){
        int v = e[i].to;
        if(v == faz) continue;
        dfs1(v,u,deep+1);
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]]||son[u] == -1)
            son[u] = v;
    }
}

void dfs2(int u,int t){
    top[u] = t;
    tid[u] = ++cnt1;
    mx[u] = cnt1;
    rk[cnt1] = u;
    if(son[u] == -1) return ;
    dfs2(son[u],t);
    for(int i = head[u];i;i=e[i].next){
        int v = e[i].to;
        if(v != fa[u]&&v != son[u])
            dfs2(v,v);
    }
    mx[u] = cnt1;
}

struct node1{
    int s[2],v;
}t[M*50];
int idx,rt[M];
void update(int &k,int p,int w){
    t[++idx] = t[k]; k = idx; t[k].v++;
    if(w == -1) return ;
    if(p&(1<<w)) update(t[k].s[1],p,w-1);
    else update(t[k].s[0],p,w-1);
}

int query(int old,int k,int p,int w){
    if(w == -1) return 0;
    int c= (bool)(p&(1<<w));
    if(t[t[k].s[c^1]].v - t[t[old].s[c^1]].v)
        return query(t[old].s[c^1],t[k].s[c^1],p,w-1)|(1<<w);
    else
        return query(t[old].s[c],t[k].s[c],p,w-1);
}

int ask(int x,int y,int z){
    int ans = 0;
    int fx = top[x],fy = top[y];
    while(fx != fy){
        if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
        ans = max(ans,query(rt[tid[fx]-1],rt[tid[x]],z,30));
        x = fa[fx]; fx = top[x];
    }
    if(dep[x] > dep[y]) swap(x,y);
    ans = max(ans,query(rt[tid[x]-1],rt[tid[y]],z,30));
    return ans;
}
int a[M];
int main()
{
    int n,q,u,v,x,y,z,op;
    scanf("%d%d",&n,&q);
    memset(son,-1,sizeof(son));
    for(int i = 1;i <= n;i ++) scanf("%d",&a[i]);
    for(int i = 1;i < n;i ++){
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    dfs1(1,0,1); dfs2(1,1);
    for(int i = 1;i <= n;i ++) rt[i]=rt[i-1],update(rt[i],a[rk[i]],30);
    while(q--){
        scanf("%d%d%d",&op,&x,&y);
        if(op == 1){
            printf("%d\n",query(rt[tid[x]-1],rt[mx[x]],y,30));
        }
        else{
            scanf("%d",&z);
            printf("%d\n",ask(x,y,z));
        }
    }
    return 0;
}

 

posted @ 2019-04-24 20:56  冥想选手  阅读(153)  评论(0编辑  收藏  举报