2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3966 Solved: 928
[Submit][Status][Discuss]
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
Input
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
Output
M行,表示每个询问的答案。
Sample Input
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
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
Sample Output
2
8
9
105
7
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。
Source
题解:
呵呵,傻逼题目搞我半天(tmd RE你是要上天啊) 就是求一颗树上区间第k大》》》So easy 妈妈在也不用担心我会RE
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 #define maxn 200010 7 #define maxnode 8000000 8 using namespace std; 9 int deep[maxn],fa[maxn][20],bin[20]; 10 int pre[maxn*2],now[maxn],v[maxn*2]; 11 int a[maxn],list[maxn]; 12 int son[maxnode][2],rt[maxn],sum[maxnode]; 13 int root,size,tot,n,m,lastans; 14 15 int read() 16 { 17 int x=0; char ch; bool bo=0; 18 while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1; 19 while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9'); 20 if (bo) return -x; return x; 21 } 22 void insert(int x,int y){++tot; pre[tot]=now[x]; now[x]=tot; v[tot]=y;} 23 void ins(int x,int y){ insert(x,y); insert(y,x); 24 } 25 void build() 26 { 27 root=0; 28 for (int i=1; i<=n-1; i++) 29 { 30 int x=read(), y=read(); 31 ins(x,y); 32 if (!root || root==y) root=x; 33 } 34 } 35 void prework() 36 { 37 bin[0]=1; 38 for (int i=1; i<=17; i++) bin[i]=bin[i-1]<<1; 39 } 40 void add(int x, int &y, int val) 41 { 42 y=++size; sum[y]=sum[x]+1; int t,pos=y; 43 int l=1,r=n; 44 while (l<r) 45 { 46 int mid=(l+r)>>1; 47 if (val<=mid) t=0,r=mid; else t=1,l=mid+1; 48 son[y][t^1]=son[x][t^1]; 49 son[y][t]=++size; 50 y=son[y][t]; x=son[x][t]; 51 sum[y]=sum[x]+1; 52 } 53 y=pos; 54 } 55 void dfs(int x,int father) 56 { 57 //cout<<" dfs "<<x<<endl; 58 deep[x]=deep[father]+1; 59 fa[x][0]=father; 60 for (int i=1; i<=17; i++) 61 if (deep[x]>=bin[i]) 62 fa[x][i]=fa[fa[x][i-1]][i-1]; 63 for (int p=now[x]; p; p=pre[p]) 64 { 65 int rz=v[p]; 66 if (rz!=father) 67 { 68 add(rt[x],rt[rz],a[rz]); 69 dfs(rz,x); 70 } 71 } 72 } 73 int lca(int x,int y) 74 { 75 if (deep[x]<deep[y]) swap(x,y); 76 int t=deep[x]-deep[y]; 77 for (int i=0; bin[i]<=t; i++) 78 { 79 if (t&bin[i]) x=fa[x][i]; 80 } 81 for (int i=16; i>=0; i--) 82 if (fa[x][i]!=fa[y][i]) 83 x=fa[x][i],y=fa[y][i]; 84 if (x==y) return x; else return fa[x][0]; 85 } 86 int query(int x, int y, int val) 87 { 88 int dad=lca(x,y),dd; 89 x=rt[x],y=rt[y]; 90 dd=fa[dad][0]; 91 dad=rt[dad],dd=rt[dd]; 92 int l=1,r=n; 93 while (l<r) 94 { 95 int mid=(l+r)>>1; int t=0; 96 int kk=sum[son[x][t]]+sum[son[y][t]]-sum[son[dad][t]]-sum[son[dd][t]]; 97 // cout<<kk<<endl; 98 if (kk>=val) 99 { 100 r=mid; x=son[x][t]; y=son[y][t]; dad=son[dad][t],dd=son[dd][t]; 101 } 102 else 103 { 104 l=mid+1; x=son[x][t^1]; y=son[y][t^1]; val-=kk,dad=son[dad][t^1],dd=son[dd][t^1]; 105 } 106 } 107 return list[l]; 108 } 109 110 int main() 111 { 112 prework(); 113 n=read(); m=read(); 114 for (int i=1; i<=n; i++) 115 a[i]=list[i]=read(); 116 sort(list+1,list+n+1); 117 for (int i=1; i<=n; i++) 118 a[i]=lower_bound(list+1,list+n+1,a[i])-list; 119 build(); 120 add(rt[0],rt[root],a[root]); 121 dfs(root,0); 122 lastans=0; 123 while (m--) 124 { 125 int x=read(),y=read(),val=read(); 126 x^=lastans; 127 lastans=query(x,y,val); 128 if (m!=0) printf("%d ",lastans); else printf("%d",lastans); 129 } 130 }