• hdu 4776 Ants(trie+优先队列)


    题目链接:hdu 4776 Ants

    题意:

    给你一棵有n个节点的树,每条边有一个权值ai,现在定义两点直接的距离为路径上经过的边的异或和。

    现在有m个询问,每次询问你第k长的路径是多少。

    题解:

    一开始我想二分+树分治+trie,发现只能做一个询问。- -!。

    这里有一个优秀的做法,可以预处理出前k个答案。

    首先,这里两点间的距离就是val[i]^val[j],val[i]表示根节点到i节点的异或和。

    然后我们可以将所有的val插进trie,然后我们将每个节点都作为起点,将以该起点的最大路径放进优先队列。

    显然当前第一大的肯定就是优先队列的top,然后我们将这个top 记录下来,并且pop掉。

    然后将产生这个top的节点x得到以x为起点的第二大路径放进优先队列。并且重复操作。

    这样就可以将前k个答案以60*n*logn的复杂度预处理出来,然后询问就可以O(1)了。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     3 #define mst(a,b) memset(a,b,sizeof(a))
     4 using namespace std;
     5 typedef long long ll;
     6 
     7 const int N=2e5+7;
     8 int n,m,g[N],v[N*2],nxt[N*2],ed;
     9 ll w[N*2],val[N],z,ans[N];
    10 int ct,x,y,cnt[N*62],tr[N*62][2],tot;
    11 struct Node
    12 {
    13     int idx,k;
    14     ll val;
    15     Node(int a=0,int b=0,ll c=0):idx(a),k(b),val(c){}
    16     bool operator<(const Node &B)const{return val<B.val;}
    17 };
    18 priority_queue<Node>Q;
    19 
    20 void adg(int x,int y,ll z){v[++ed]=y,w[ed]=z,nxt[ed]=g[x],g[x]=ed;}
    21 
    22 void dfs(int x,ll va,int fa)
    23 {
    24     val[x]=va;
    25     for(int i=g[x];i;i=nxt[i])
    26         if(v[i]!=fa)dfs(v[i],va^w[i],x);
    27 }
    28 
    29 void ins(ll a,int x=1)
    30 {
    31     for(int i=60;i>=0;i--)
    32     {
    33         int w=(a>>i)&1;
    34         if(!tr[x][w])
    35         {
    36             cnt[++tot]=0,mst(tr[tot],0);
    37             tr[x][w]=tot;
    38         }
    39         x=tr[x][w],cnt[x]++;
    40     }
    41 }
    42 
    43 ll kth(ll a,int k,int x=1,int i=60)
    44 {
    45     if(i<0)return 0;
    46     int w=(a>>i)&1;
    47     if(tr[x][w^1]&&cnt[tr[x][w^1]]>=k)
    48         return (1ll*(w^1)<<i)|kth(a,k,tr[x][w^1],i-1);
    49     return (1ll*w<<i)|kth(a,k-cnt[tr[x][w^1]],tr[x][w],i-1);
    50 }
    51 
    52 void init(){mst(g,0),ed=ct=0,mst(tr[1],0),cnt[tot=1]=0;}
    53 
    54 int main(){
    55     while(scanf("%d",&n),n)
    56     {
    57         init();
    58         while(!Q.empty())Q.pop();
    59         F(i,1,n-1)
    60         {
    61             scanf("%d%d%lld",&x,&y,&z);
    62             adg(x,y,z),adg(y,x,z);
    63         }
    64         dfs(1,0,0);
    65         F(i,1,n)ins(val[i]);
    66         F(i,1,n)
    67         {
    68             ll now=kth(val[i],1)^val[i];
    69             Q.push(Node(i,1,now));
    70         }
    71         while(ct<=200000&&!Q.empty())
    72         {
    73             Node now=Q.top();Q.pop();
    74             ans[++ct]=now.val;
    75             if(now.k+1>n)continue;
    76             ll tp=kth(val[now.idx],now.k+1)^val[now.idx];
    77             Q.push(Node(now.idx,now.k+1,tp));
    78         }
    79         scanf("%d",&m);
    80         F(i,1,m)
    81         {
    82             scanf("%d",&x);
    83             printf("%lld
    ",(x>ct||n==1)?-1:ans[x]);
    84         }
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    spring MVC fromeWork 與webwork2 mvc 比較
    JAVA Oauth 认证服务器的搭建
    HTTPS的工作原理
    理解HTTP幂等性
    支付交易一般性准则
    设计模式六大原则
    腾讯微信技术总监周颢:一亿用户增长背后的架构秘密
    Valid Parentheses
    4Sum
    Letter Combinations of a Phone Number
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7652599.html
Copyright © 2020-2023  润新知