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
暴力自重。。。

Solution

emmmLCA求错了然后debug了1h的丢人事迹我是不会说的
一开始看到这个题以为是点分,然后发现没法做。
现在做主席树的时候做到这个题了
就想在DFS序上搞事情……就像链剖一样……然后GG了
偷看了一眼题解的第一行发现用Root[i]表示路径[1,i]情况
然后就没什么思维难度了……
对于路径[u,v]的离散化后的值域情况
我们可以用segt[v]+segt[u]-segt[lca]-segt[father[lca]]来计算
然后就是求第k大的模板了
建树的时候有点小技巧(见代码)

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N (100000+100)
using namespace std;
struct node{int sum,lson,rson;}Segt[N*];
struct node1{int to,next;}edge[N*];
int a[N],b[N],n,m,Root[N],segt_num,u,v,x,y,k,num,lastans;
int head[N],num_edge,Father[N],f[N][],Depth[N]; void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} int Build(int l,int r)
{
int node=++segt_num;
if (l==r) return node;
int mid=(l+r)>>;
Segt[node].lson=Build(l,mid);
Segt[node].rson=Build(mid+,r);
return node;
} int Update(int pre,int l,int r,int x)
{
int node=++segt_num;
Segt[node].sum=Segt[pre].sum+;
Segt[node].lson=Segt[pre].lson;
Segt[node].rson=Segt[pre].rson;
if (l==r) return node;
int mid=(l+r)>>;
if (x<=mid) Segt[node].lson=Update(Segt[node].lson,l,mid,x);
else Segt[node].rson=Update(Segt[node].rson,mid+,r,x);
return node;
} void Dfs1(int x)
{
Depth[x]=Depth[Father[x]]+;
for (int i=head[x];i;i=edge[i].next)
if (edge[i].to!=Father[x])
{
Father[edge[i].to]=f[edge[i].to][]=x;
Dfs1(edge[i].to);
}
} void Dfs2(int x)
{
int t=lower_bound(b+,b+num+,a[x])-b;
Root[x]=Update(Root[Father[x]],,num,t);//因为这里父亲的主席树已经建立好了,所以这个点的主席树就可以建立了
for (int i=head[x];i;i=edge[i].next)
if (edge[i].to!=Father[x])
Dfs2(edge[i].to);
} int Query(int u,int v,int lca,int flca,int l,int r,int k)
{
if (l==r) return b[l];
int mid=(l+r)>>,x=Segt[Segt[u].lson].sum+Segt[Segt[v].lson].sum-Segt[Segt[lca].lson].sum-Segt[Segt[flca].lson].sum;
if (k<=x) return Query(Segt[u].lson,Segt[v].lson,Segt[lca].lson,Segt[flca].lson,l,mid,k);
else return Query(Segt[u].rson,Segt[v].rson,Segt[lca].rson,Segt[flca].rson,mid+,r,k-x);
} int LCA(int x,int y)
{
if (Depth[x]<Depth[y]) swap(x,y);
for (int i=;i>=;--i)
if (Depth[f[x][i]]>=Depth[y])
x=f[x][i];
if (x==y) return y;
for (int i=;i>=;--i)
if (f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return Father[x];
} int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;++i)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+);
num=unique(b+,b+n+)-b-;
Root[]=Build(,num);//多一个0点方便处理,作为1的父亲
add(,); add(,);
for (int i=;i<=n-;++i)
{
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
Dfs1();//以1为根建树
for (int i=;i<=;++i)
for (int j=;j<=n;++j)
f[j][i]=f[f[j][i-]][i-];
Dfs2();//建立主席树
for (int i=;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&k);
x^=lastans;
int lca=LCA(x,y);
printf("%d\n",lastans=Query(Root[x],Root[y],Root[lca],Root[Father[lca]],,num,k));
}
}

BZOJ2588:Count on a tree(主席树)的更多相关文章

  1. 洛谷P2633/bzoj2588 Count on a tree (主席树)

    洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...

  2. [bzoj2588][count on a tree] (主席树+lca)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

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

    [BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...

  4. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

  5. 【bzoj2588】Count on a tree 主席树

    这题给人开了个新思路. 原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间. 此题若带修改怎么办? 若对某个点的权值做修改,则这个点的子树都会受影响,想 ...

  6. spoj cot: Count on a tree 主席树

    10628. Count on a tree Problem code: COT You are given a tree with N nodes.The tree nodes are number ...

  7. Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...

  8. 洛谷P2633 Count on a tree(主席树上树)

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  9. SPOJ Count on a tree(主席树+LCA)

    一.题目 COT - Count on a tree You are given a tree with N nodes. The tree nodes are numbered from 1 to  ...

随机推荐

  1. Universal App图片文件和图片byte[]信息转换为bitmap

    1. 打开图片文件并转换为BitmapImage类 首先要做的自然是打开一个图片文件了,可以使用FileOpenPicker来手动选择图片,总之能拿到一个StorageFile都行. //打开图片选择 ...

  2. 来一波Linux中查看cpu、磁盘、内存、网络的命令

    转载请注明出处. 如果想远程管理服务器就有远程管理卡,比如Dell idRAC,HP ILO,IBM IMM 查看硬件的温度/风扇转速,电脑有撸大师,服务器就有ipmitool.使用ipmitool实 ...

  3. Html与Css关联到一起

    在HTML文件中使用Link标签连接独立的Css文件 将Link标签放在head标签中 like标签是空标签,只写开始标签,不写结束标签 我们需要为like标签设置一些属性 type的值设置为text ...

  4. Docker学习(二): 镜像的使用与构建

    特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! =============系列文章============= 1 ...

  5. C#生成Excel

    需要引用MyXls.SL2.dll的类库: 下载地址:http://sourceforge.net/projects/myxls/ 命名空间using org.in2bits.MyXls: //创建表 ...

  6. FileSystemWatcher 监视指定目录中的变更

    .Net框架类库中的FileSystemWatcher如它的名称一样是一个用于监视文件系统变化的一个控件.使用 FileSystemWatcher 监视指定目录中的更改.可监视指定目录中的文件或子目录 ...

  7. HTML中字体的垂直排列

    1.源代码: <html> <head> </head> <body> <div style="font-size:18px;writi ...

  8. 【Java学习经历系列-1】19岁的我,没遇见生命中的她,却遇见了java

    [写在前面]正直青春年少的你,遇到了你的她了吗?还是你也和我们今天的主人公一样,在最美好的年级,正在为你的初衷努力着,坚持着,奔波着..... 作者:李伟   我的黑客时代 01 大学专业是电子信息工 ...

  9. Python随笔目录

    Python 一.Python基础 Python入门 数据类型 函数(迭代器生成器三元表达式) 模块和常用内置模块 面向对象 网络编程(socket) 并发编程 ... 二.数据库 MySQL PyM ...

  10. CentOS配置multipath

    可以通过2种方式查看HBA的WWN信息: 1. 查看sys文件系统 查看HBA卡型号:[root@localhost ~]# lspci  | grep -i fibre13:00.0 Fibre C ...