1. 程式人生 > >bzoj2588 Spoj10628. count on a tree

bzoj2588 Spoj10628. count on a tree

簡單 head 描述 b- 上一個 主席樹 ace pre 輸入輸出格式

題目描述

給定一棵N個節點的樹,每個點有一個權值,對於M個詢問(u,v,k),你需要回答u xor lastans和v這兩個節點間第K小的點權。其中lastans是上一個詢問的答案,初始為0,即第一個詢問的u是明文。

輸入輸出格式

輸入格式:

第一行兩個整數N,M。

第二行有N個整數,其中第i個整數表示點i的權值。

後面N-1行每行兩個整數(x,y),表示點x到點y有一條邊。

最後M行每行兩個整數(u,v,k),表示一組詢問。

輸出格式:

M行,表示每個詢問的答案。

輸入輸出樣例

輸入樣例#1:
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

暴力自重。。。

題解

其實就是個很簡單的主席樹,只要把在序列上的建樹改成在樹上建就可以了

雖然我也是今天看到這道題看完題解才知道怎麽在樹上建主席樹

關於路徑,可以在樹上差分一下用$sum[l]+sum[r]-sum[lca]-sum[lca_fa]$

然後因為要求lca,所以在樹剖dfs的時候順便建一下主席樹就好了

具體實現請參考代碼

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 #define N 100005
 4
#define M 2000005 5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 inline int read(){ 9 #define num ch-‘0‘ 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc()))
12 (ch==-)&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 int sum[M],L[M],R[M]; 19 int a[N],b[N],rt[N]; 20 int fa[N],sz[N],d[N],ver[N<<1],Next[N<<1],head[N],son[N],top[N]; 21 int n,q,m,cnt=0,tot=0,ans=0; 22 void update(int last,int &now,int l,int r,int x){ 23 sum[now=++cnt]=sum[last]+1; 24 if(l==r) return; 25 int mid=(l+r)>>1; 26 if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x); 27 else L[now]=L[last],update(R[last],R[now],mid+1,r,x); 28 } 29 inline void add(int u,int v){ 30 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 31 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 32 } 33 void dfs(int u){ 34 sz[u]=1,d[u]=d[fa[u]]+1; 35 update(rt[fa[u]],rt[u],1,m,a[u]); 36 for(int i=head[u];i;i=Next[i]){ 37 int v=ver[i]; 38 if(v==fa[u]) continue; 39 fa[v]=u,dfs(v); 40 sz[u]+=sz[v]; 41 if(!son[u]||sz[v]>sz[son[u]]) son[u]=v; 42 } 43 } 44 void dfs(int u,int tp){ 45 top[u]=tp; 46 if(!son[u]) return; 47 dfs(son[u],tp); 48 for(int i=head[u];i;i=Next[i]){ 49 int v=ver[i]; 50 if(v==son[u]||v==fa[u]) continue; 51 dfs(v,v); 52 } 53 } 54 int LCA(int x,int y){ 55 while(top[x]!=top[y]) 56 d[top[x]]>=d[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 57 return d[x]>=d[y]?y:x; 58 } 59 int query(int ql,int qr,int lca,int lca_fa,int l,int r,int k){ 60 if(l>=r) return l; 61 int x=sum[L[ql]]+sum[L[qr]]-sum[L[lca]]-sum[L[lca_fa]]; 62 int mid=(l+r)>>1; 63 if(x>=k) return query(L[ql],L[qr],L[lca],L[lca_fa],l,mid,k); 64 else return query(R[ql],R[qr],R[lca],R[lca_fa],mid+1,r,k-x); 65 } 66 int main(){ 67 //freopen("testdata.in","r",stdin); 68 n=read(),q=read(); 69 for(int i=1;i<=n;++i) 70 b[i]=a[i]=read(); 71 sort(b+1,b+1+n); 72 m=unique(b+1,b+1+n)-b-1; 73 for(int i=1;i<=n;++i) 74 a[i]=lower_bound(b+1,b+1+m,a[i])-b; 75 for(int i=1;i<n;++i){ 76 int u=read(),v=read(); 77 add(u,v); 78 } 79 dfs(1),dfs(1,1); 80 while(q--){ 81 int x,y,z,lca; 82 x=read(),y=read(),z=read(); 83 x^=ans,lca=LCA(x,y); 84 ans=b[query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,m,z)]; 85 printf("%d\n",ans); 86 } 87 return 0; 88 }

bzoj2588 Spoj10628. count on a tree