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\n",(x>ct||n==1)?-1:ans[x]); 84 } 85 } 86 return 0; 87 }