bzoj2588

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2
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\n",lastans); else printf("%d",lastans);
129     }
130 }
View Code

 

posted @ 2016-04-30 17:48  ACist  阅读(202)  评论(0编辑  收藏  举报