zoukankan      html  css  js  c++  java
  • [TJOI2018]异或

    这大概是这个题最蒻的一篇题解了吧,供不会可持久化$Trie$且在解决本题之前不想学会的人食用

    并不会可持久化$Trie$的蒟蒻本蒻遇到了这个题,然后用$Trie$维护的树链剖分水过去了

    数集中的数与询问的异或最大值求解思路

    思路很常见,比较好想,对数集中的所有数从高位到低位建立$01Trie$,然后贪心求解即可——设目前匹配到从高到低的第$i$位,若询问$x$的第$i$位为0,则优先进入到$Trie$树中当前节点的1方向,意义为在原最优解集上选择了所有第$i$位为1的数构成的子集作为新的最优解集,答案增加$2^{i-1}$,若当前节点的1方向不存在(原最优解集中不存在第$i$位为1的数)则进入0方向,答案不更新,询问$x$的第$i$位为1则相反,不再赘述。由进制的性质可得,贪心策略的正确性显然

    考虑本题

    子树问题常常通过$dfs$序解决,链上问题常常通过树链剖分解决,而树链剖分在其执行过程中维护了$dfs$序,故考虑通过树链剖分解决问题

    树链剖分的查询按$dfs$序是区间连续的,故只需维护$Trie$上的每个节点对应的数集(以每个节点的$dfs$序为代表),对于每个查询在数集上进行二分,判断查询区间内$0/1$方向的节点的存在性即可

    时间复杂度会比可持久化$Trie$多一个$log$,不过也是可过的

    代码

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    struct edge{
        int next,to;
    }e[maxn*2];
    vector<int>vc[maxn*30];
    int n,m,v[maxn],head[maxn],cnt,f[maxn],d[maxn],son[maxn];
    int tr[maxn*30][2],size[maxn],top[maxn],id[maxn],rk[maxn];
    void insert(int x,int id)
    {
        for(int now=0,i=29;i>=0;i--)
        {
            int c=(x&(1<<i))?1:0;
            now=tr[now][c]?tr[now][c]:tr[now][c]=++cnt;
            vc[now].push_back(id);
        }
    }
    int query(int x,int y,int k)
    {
        int ret=0;
        for(int now=0,i=29;i>=0;i--)
        {
            int to=(k&(1<<i))?0:1,trs=tr[now][to];
            if(upper_bound(vc[trs].begin(),vc[trs].end(),y)-lower_bound(vc[trs].begin(),vc[trs].end(),x))
                now=tr[now][to],ret+=(1<<i);
            else
                now=tr[now][to^1];
        }
        return ret;
    }
    void add(int x,int y)
    {
        e[++cnt].next=head[x];
        e[cnt].to=y;
        head[x]=cnt;
    }
    void dfs1(int x)
    {
        size[x]=1,d[x]=d[f[x]]+1;
        for(int v,i=head[x];i;i=e[i].next)
            if((v=e[i].to)!=f[x])
            {
                f[v]=x,dfs1(v),size[x]+=size[v];
                if(size[son[x]]<size[v])
                    son[x]=v;
            }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp,id[x]=++cnt,rk[cnt]=x;
        if(son[x])
            dfs2(son[x],tp);
        for(int v,i=head[x];i;i=e[i].next)
            if((v=e[i].to)!=f[x]&&v!=son[x])
                dfs2(v,v);
    }
    int sum(int x,int y,int k)
    {
        int ret=0;
        while(top[x]!=top[y])
        {
            if(d[top[x]]<d[top[y]])
                swap(x,y);
            ret=max(ret,query(id[top[x]],id[x],k));
            x=f[top[x]];
        }
        if(id[x]>id[y])
            swap(x,y);
        return ret=max(ret,query(id[x],id[y],k));
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&v[i]);
        for(int x,y,i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        cnt=0,dfs1(1),dfs2(1,1),cnt=0;
        for(int i=1;i<=n;i++)
            insert(v[rk[i]],i);
        for(int op,x,y,k,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==1)
                printf("%d
    ",query(id[x],id[x]+size[x]-1,y));
            else
            {
                scanf("%d",&k);
                printf("%d
    ",sum(x,y,k));
            }
        }
        return 0;
    }
  • 相关阅读:
    React在componentDidMount里面发送请求
    React 术语词汇表
    React里受控与非受控组件
    React和Vue等框架什么时候操作DOM
    【LeetCode】79. Word Search
    【LeetCode】91. Decode Ways
    【LeetCode】80. Remove Duplicates from Sorted Array II (2 solutions)
    【LeetCode】1. Two Sum
    【LeetCode】141. Linked List Cycle (2 solutions)
    【LeetCode】120. Triangle (3 solutions)
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/14394743.html
Copyright © 2011-2022 走看看