給定一棵N個節點的樹,每一個點有一個權值,對於M個詢問(u,v,k),你須要回答u xor lastans和v這兩個節點間第K小的點權。其中lastans是上一個詢問的答案,初始爲0,即第一個詢問的u是明文。php
輸入格式:c++
第一行兩個整數N,M。spa
第二行有N個整數,其中第i個整數表示點i的權值。code
後面N-1行每行兩個整數(x,y),表示點x到點y有一條邊。get
最後M行每行兩個整數(u,v,k),表示一組詢問。it
輸出格式:io
M行,表示每一個詢問的答案。ast
輸入樣例#1:class
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2查詢
輸出樣例#1:
2
8
9
105
7
HINT:
N,M<=100000
暴力自重。。。
來源:bzoj2588 Spoj10628.
bzoj題面傳送門
無修改,樹上路徑查詢k小值
k小值能夠主席樹解決,樹上路徑其實不用真的提出來,咱們能夠運用差分的思路,因爲是點差,求出它的\(lca,\)那麼\(ans=a[u]+a[v]-a[lca]-a[fa[lca]]\).
具體到這道題就是\(u\)的主席樹\(+v\)的主席樹\(-lca\)的主席樹\(-fa[lca]\)的主席樹
\(lca\)倍增求就能夠了
#include<bits/stdc++.h> #define in(i) (i=read()) #define il extern inline #define rg register #define mid ((l+r)>>1) #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define lol long long using namespace std; const int N=1e5+10; int read() { int ans=0, f=1; char i=getchar(); while (i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();} while (i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48), i=getchar(); return ans*f; } int n,m,cur,num,tot,pre; int head[N],nex[N<<1],to[N<<1]; int f[25][N],lg[N]={-1},dep[N]; int a[N],h[N],rt[N<<6]; struct Chair_Tree { int l,r,v; }t[N<<6]; void add(int a,int b) { to[++cur]=b,nex[cur]=head[a],head[a]=cur; to[++cur]=a,nex[cur]=head[b],head[b]=cur; } void insert(int &u,int l,int r,int pre,int p) { t[u=++tot]=t[pre], t[u].v++; if(l==r) return; if(p<=mid) insert(t[u].l,l,mid,t[pre].l,p); else insert(t[u].r,mid+1,r,t[pre].r,p); } int query(int a,int b,int c,int d,int l,int r,int k) { int AQ=t[t[a].l].v+t[t[b].l].v-t[t[c].l].v-t[t[d].l].v; if(l==r) return h[l]; if(k<=AQ) return query(t[a].l,t[b].l,t[c].l,t[d].l,l,mid,k); else return query(t[a].r,t[b].r,t[c].r,t[d].r,mid+1,r,k-AQ); } void dfs(int u) { a[u]=lower_bound(h+1,h+1+num,a[u])-h; insert(rt[u],1,num,rt[f[0][u]],a[u]); for (int i=head[u];i;i=nex[i]) { if(to[i]==f[0][u]) continue; dep[to[i]]=dep[u]+1, f[0][to[i]]=u; dfs(to[i]); } } void init() { for (int i=1;i<=n;i++) lg[i]=lg[i>>1]+1; for (int i=1;i<=lg[n];i++) for (int j=1;j<=n;j++) f[i][j]=f[i-1][f[i-1][j]]; } int LCA(int a,int b) { if(dep[a]>dep[b]) swap(a,b); int s=dep[b]-dep[a]; for (int i=lg[s];i>=0;i--) if(s>>i&1) b=f[i][b]; if(a==b) return a; for (int i=lg[n];i>=0;i--) { if(f[i][a]==f[i][b]) continue; a=f[i][a], b=f[i][b]; }return f[0][a]; } int main() { in(n), in(m); for (int i=1;i<=n;i++) in(a[i]),h[i]=a[i]; sort(h+1,h+1+n); num=unique(h+1,h+1+n)-h-1; for (int i=1,x,y;i<n;i++) in(x),in(y),add(x,y); dep[1]=1, dfs(1), init(); for (int i=1,a,b,k;i<=m;i++) { in(a),in(b),in(k),a^=pre; int lca=LCA(a,b); printf("%d\n",pre=query(rt[a],rt[b],rt[lca],rt[f[0][lca]],1,num,k)); } }