bzoj 2588: Spoj 10628. Count on a tree

DFS序在树上建出主席树,然后。。。。。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #define ll long long
  8 #define M 200009
  9 using namespace std;
 10 ll read()
 11 {
 12   ll x=0,f=1;
 13   char ch=getchar();
 14   for(;ch<‘0‘||ch>‘9‘;ch=getchar())
 15     if(ch==‘-‘)
 16       f=-1;
 17   for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar())
 18     x=x*10+ch-‘0‘;
 19   return x*f;
 20 }
 21 int lc[M][20],head[M],next[M],u[M],cnt,n,m,v[M],v1[M],n1,deep[M],pos[M],num[M],T,root[M];
 22 int tot,lastans;
 23 struct data
 24 {
 25     int l,r,sum;
 26 }a[20*M];
 27 void jia(int a1,int a2)
 28 {
 29     next[++cnt]=head[a1];
 30     head[a1]=cnt;
 31     u[cnt]=a2;
 32 }
 33 void dfs(int x)
 34 {
 35     num[++T]=x;
 36     pos[x]=T;
 37     for(int i=1;(1<<i)<=deep[x];i++)
 38         lc[x][i]=lc[lc[x][i-1]][i-1];
 39     for(int i=head[x];i;i=next[i])
 40       if(u[i]!=lc[x][0])
 41       {
 42           deep[u[i]]=deep[x]+1;
 43           lc[u[i]][0]=x;
 44           dfs(u[i]);
 45       }
 46 }
 47 void geng(int l,int r,int x,int &y,int z)
 48 {
 49     y=++tot;
 50     a[y].sum=a[x].sum+1;
 51     if(l==r)
 52       return;
 53     a[y].l=a[x].l;
 54     a[y].r=a[x].r;
 55     int mid=(l+r)>>1;
 56     if(mid>=z)
 57         geng(l,mid,a[x].l,a[y].l,z);
 58     else
 59         geng(mid+1,r,a[x].r,a[y].r,z);
 60 }
 61 int lca(int a1,int a2)
 62 {
 63     if(deep[a1]<deep[a2])
 64         swap(a1,a2);
 65     int a3=deep[a1]-deep[a2];
 66     for(int i=0;i<=16;i++)
 67         if(a3&(1<<i))
 68           a1=lc[a1][i];
 69     for(int i=16;i>=0;i--)
 70         if(lc[a1][i]!=lc[a2][i])
 71       {
 72           a1=lc[a1][i];
 73           a2=lc[a2][i];
 74       }
 75     if(a1==a2)
 76         return a1;
 77     return lc[a1][0];
 78 }
 79 int cha(int u,int v,int t,int k)
 80 {
 81     int a1=root[pos[u]],a2=root[pos[v]],a3=root[pos[t]],a4=root[pos[lc[t][0]]];
 82     int l=1,r=n1-1,ans;
 83     for(;;)
 84       {
 85           if(l==r)
 86               return v1[l];
 87           int mid=(l+r)>>1;
 88           int a5=a[a[a1].l].sum+a[a[a2].l].sum-a[a[a3].l].sum-a[a[a4].l].sum;
 89           if(a5>=k)
 90             {
 91                 r=mid;
 92                 a1=a[a1].l;
 93                 a2=a[a2].l;
 94                 a3=a[a3].l;
 95                 a4=a[a4].l;
 96             }
 97           else
 98             {
 99                 k-=a5;
100                 l=mid+1;
101                 a1=a[a1].r;
102                 a2=a[a2].r;
103                 a3=a[a3].r;
104                 a4=a[a4].r;
105             }
106       }
107 }
108 int main()
109 {
110     n=read();
111     m=read();
112     for(int i=1;i<=n;i++)
113       v1[i]=v[i]=read();
114     sort(v1+1,v1+n+1);
115     n1=unique(v1+1,v1+n+1)-v1;
116     for(int i=1;i<=n;i++)
117       v[i]=lower_bound(v1+1,v1+n1,v[i])-v1;
118     for(int i=1;i<n;i++)
119       {
120           int a1=read(),a2=read();
121           jia(a1,a2);
122           jia(a2,a1);
123       }
124     dfs(1);
125     for(int i=1;i<=n;i++)
126       geng(1,n1-1,root[pos[lc[num[i]][0]]],root[i],v[num[i]]);
127     for(int i=1;i<=m;i++)
128       {
129           int u=read()^lastans,v=read(),k=read();
130           int t=lca(u,v);
131           printf("%d",lastans=cha(u,v,t,k));
132           if(i!=m)
133             printf("\n");
134       }
135     return 0;
136 }
时间: 2024-12-12 22:56:22

bzoj 2588: Spoj 10628. Count on a tree的相关文章

BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

2588: Spoj 10628. Count on a tree 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),表示一组询问.

bzoj 2588: Spoj 10628. Count on a tree LCA+主席树

2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数

BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233[Submit][Status][Discuss] Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一

BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2588 Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Inp

【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

[BZOJ2588]Spoj 10628. Count on a tree 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),表示一组

SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight. We will ask you to perform the following operation: u v k : ask for the kth minimum weight on the path from node u 

bzoj2588: Spoj 10628. Count on a tree(树上第k大)(主席树)

每个节点继承父节点的树,则答案为query(root[x]+root[y]-root[lca(x,y)]-root[fa[lca(x,y)]]) #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> using namespace std; const int maxn=100010; struct poi{int s

Spoj 10628. Count on a tree

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行,表示每个询问的答案.最后一个询问不输出换行符 S

BZOJ2588 Spoj 10628. Count on a tree

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! 题目链接:BZOJ2588 SPOJ10628 正解:主席树上树 解题报告: 考虑主席树上树,每次build都是儿子在父亲的基础上build,然后查询的话就是对于x到y的路径,令$Tx$为$x$对应的线段树,那就是$T_x+T_y-T_{lca}-T_{f