• P4592 [TJOI2018]异或


    链接:https://www.luogu.org/problemnew/show/P4592

    题目描述

    现在有一颗以 11 为根节点的由 nn 个节点组成的树,树上每个节点上都有一个权值 v_ivi 。现在有 QQ 次操作,操作如下:

    • 1;x;y1xy :查询节点 xx 的子树中与 yy 异或结果的最大值
    • 2;x;y;z2xyz :查询路径 xx 到 yy 上点与 zz 异或结果最大值

    输入输出格式

    输入格式:

    第一行是两个数字 n,Qn,Q ;

    第二行是 nn 个数字用空格隔开,第 ii 个数字 v_ivi 表示点 ii 上的权值

    接下来 n-1n1 行,每行两个数, x,yx,y ,表示节点 xx 与 yy 之间有边

    接下来 QQ 行,每一行为一个查询,格式如上所述.

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    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
    输出样例#1: 复制
    7
    6
    12
    11
    14

    说明

    对于 10\%10% 的数据,有 1<n,,Q100

    对于 20\%20% 的数据,有 1<n,,Q1000

    对于 40\%40% 的数据,有 1<n,,Q10000

    对于 100\%100% 的数据,有 1<n,Q100000

    对于 100\%100% 的数据,有查询 11 中的y2^30 ,查询 22 中的 z2^30 。

    题解:贪心+可持续化Trie树; 对于子树查询用dfn序; 对于链上查询, 我们对每个点建一个他到根节点的Trie树,然后跑lca,又变成了序列上的查询;

    好久不写倍增都错了

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 100005, Trie_M = 1e7;
    #define ll long long
    #define For(a, b, c) for(int a = b; a <= c; a++)
    #define ex(i, u) for(int i = h[u]; i; i = G[i].nxt)
    
    int dep[M], out[M], dfn[M], val[M], nval[M], root[M], h[M], anc[M][20], tot, idx, cnt;
    ll bin[35];
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        return x*=f;
    }
    struct edge{ int v, nxt;}G[M << 1];
    void add(int u, int v){G[++tot].v = v; G[tot].nxt = h[u]; h[u] = tot;}
    
    struct Trie{
        int root[M];
        struct Tree{
            int ch[2], ptr[2];
        }tree[Trie_M];
        
        void ins(int f, int &now, int x, int c = 0){
            now = ++cnt;
            int res = now;
            tree[res] = tree[f];
            
            for(int i = 31; i >= 0; i--){
                int d = (x & bin[i]) ? 1 : 0;
                tree[res].ch[d]++;
                int p = ++cnt;
                tree[res].ptr[d] = p;
                f = tree[f].ptr[d];
                tree[p] = tree[f];
                res = tree[res].ptr[d];    
                //printf("%d ", d);        
            }
            //printf("
    ");
        }
        
        
        ll query(int lf, int rg, int x){
            ll ret = 0;
            for(int i = 31; i >= 0; i--){
                int d = (x & bin[i]) ? 1 : 0;
                if(tree[rg].ch[d^1] - tree[lf].ch[d^1]){
                    lf = tree[lf].ptr[d^1], rg = tree[rg].ptr[d^1];
                    ret += bin[i];
                }    
                else lf = tree[lf].ptr[d], rg = tree[rg].ptr[d];
            }
            return ret;    
        }
        
    }xuelie, zishu;
    
    
    void dfs(int u, int f){
        dfn[u] = ++idx;
        nval[idx] = val[u];
        dep[u] = dep[f] + 1;
        
        anc[u][0] = f;
        For(p, 1, 19)
            anc[u][p] = anc[anc[u][p - 1]][p - 1];
        
        xuelie.ins(xuelie.root[f], xuelie.root[u], val[u]);
        
        ex(i, u){
            int v = G[i].v;
            if(v == f)continue;
            dfs(v, u);
        }
        out[u] = idx;
    }
    
    int find_lca(int u, int v){
        if(dep[u] < dep[v])swap(u, v);
        int t = dep[u] - dep[v];
        for(int p = 0; t; t >>= 1, p++)
            if(t & 1)u = anc[u][p];
        if(u == v)return u;
        for(int p = 19; p >= 0; p--)
            if(anc[u][p] != anc[v][p])
                u = anc[u][p], v = anc[v][p];
        return anc[u][0];
    }
    
    
    
    
    int main(){
        //freopen("data.out","r",stdin);
        //freopen("my.out","w",stdout);
        int n, Q;
        bin[0] = 1;
        For(i, 1, 32) bin[i] = bin[i - 1] << 1;
        
        scanf("%d%d", &n, &Q);
        For(i, 1, n) val[i] = read();
        For(i, 1, n-1){
            int u = read(), v = read();
            add(u, v);
            add(v, u);
        }
        dfs(1, 0);
        For(i, 1, n) zishu.ins(zishu.root[i - 1], zishu.root[i], nval[i]);
        
        int opt, x, y, z;
        For(i, 1, Q){
            opt = read(), x = read(), y = read();
            if(opt == 1){
                printf("%lld
    ", zishu.query(zishu.root[dfn[x] - 1], zishu.root[out[x]], y));
            }
            else {
                int z = read();
                int flca = anc[find_lca(x, y)][0];
                //printf("%d      ", flca);
                ll ans = max(xuelie.query(xuelie.root[flca], xuelie.root[x], z), xuelie.query(xuelie.root[flca], xuelie.root[y], z));
                printf("%lld
    ",ans);
            }
        }
        
    }
    
    /*
    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
    */
    View Code
  • 相关阅读:
    讯时新闻系统再探
    三顾讯时对讯时新闻发布系统的艰难突破
    MsSQL注入猜解数据库技术
    提取中国IP段信息
    翻译杂感 via刘未鹏
    学习密度与专注力
    Cross Compilation Toolchains
    RHEL/CentOS 6.0使用第三方软件库(EPEL与RPMForge、RPMFusion软件库)
    一个很好的shell配置文件
    Cloud Computing
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9470072.html
Copyright © 2020-2023  润新知