bzoj2588 Spoj10628. count on a tree
题目描述
给定一棵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行,表示每个询问的答案。
输入输出样例
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
2
8
9
105
7
说明
HINT:
N,M<=100000
暴力自重。。。
题解
其实就是个很简单的主席树,只要把在序列上的建树改成在树上建就可以了
虽然我也是今天看到这道题看完题解才知道怎么在树上建主席树
关于路径,可以在树上差分一下用$sum[l]+sum[r]-sum[lca]-sum[lca_fa]$
然后因为要求lca,所以在树剖dfs的时候顺便建一下主席树就好了
具体实现请参考代码
//minamoto
#include<bits/stdc++.h>
#define N 100005
#define M 2000005
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
int sum[M],L[M],R[M];
int a[N],b[N],rt[N];
int fa[N],sz[N],d[N],ver[N<<],Next[N<<],head[N],son[N],top[N];
int n,q,m,cnt=,tot=,ans=;
void update(int last,int &now,int l,int r,int x){
sum[now=++cnt]=sum[last]+;
if(l==r) return;
int mid=(l+r)>>;
if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
else L[now]=L[last],update(R[last],R[now],mid+,r,x);
}
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
void dfs(int u){
sz[u]=,d[u]=d[fa[u]]+;
update(rt[fa[u]],rt[u],,m,a[u]);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v==fa[u]) continue;
fa[v]=u,dfs(v);
sz[u]+=sz[v];
if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs(int u,int tp){
top[u]=tp;
if(!son[u]) return;
dfs(son[u],tp);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v==son[u]||v==fa[u]) continue;
dfs(v,v);
}
}
int LCA(int x,int y){
while(top[x]!=top[y])
d[top[x]]>=d[top[y]]?x=fa[top[x]]:y=fa[top[y]];
return d[x]>=d[y]?y:x;
}
int query(int ql,int qr,int lca,int lca_fa,int l,int r,int k){
if(l>=r) return l;
int x=sum[L[ql]]+sum[L[qr]]-sum[L[lca]]-sum[L[lca_fa]];
int mid=(l+r)>>;
if(x>=k) return query(L[ql],L[qr],L[lca],L[lca_fa],l,mid,k);
else return query(R[ql],R[qr],R[lca],R[lca_fa],mid+,r,k-x);
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),q=read();
for(int i=;i<=n;++i)
b[i]=a[i]=read();
sort(b+,b++n);
m=unique(b+,b++n)-b-;
for(int i=;i<=n;++i)
a[i]=lower_bound(b+,b++m,a[i])-b;
for(int i=;i<n;++i){
int u=read(),v=read();
add(u,v);
}
dfs(),dfs(,);
while(q--){
int x,y,z,lca;
x=read(),y=read(),z=read();
x^=ans,lca=LCA(x,y);
ans=b[query(rt[x],rt[y],rt[lca],rt[fa[lca]],,m,z)];
printf("%d\n",ans);
}
return ;
}
bzoj2588 Spoj10628. count on a tree的更多相关文章
- BZOJ2588 SPOJ10628 Count on a tree 【主席树】
BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- [bzoj2588][Spoj10628]Count on a tree_主席树
Count on a tree bzoj-2588 Spoj-10628 题目大意:给定一棵n个点的树,m次查询.查询路径上k小值. 注释:$1\le n,m\le 10^5$. 想法:好像更博顺序有 ...
- 【BZOJ-2588】Count on a tree 主席树 + 倍增
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3749 Solved: 873[ ...
- 【bzoj2588】Count on a tree
Portal -->bzoj2588 Solution 不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢..) 额首先说一下正解 如果这个问题放在序列上面的话..直接离散化一下然后 ...
- BZOJ2588:Count on a tree——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2588 Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你 ...
- 主席树+LCA【p2633 (bzoj2588】 Count on a tree
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【bzoj2588】Count on a tree 主席树
这题给人开了个新思路. 原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间. 此题若带修改怎么办? 若对某个点的权值做修改,则这个点的子树都会受影响,想 ...
- 【BZOJ2588】Count on a tree 题解(主席树+LCA)
前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...
随机推荐
- 【codeforces 103E】 Buying Sets
http://codeforces.com/problemset/problem/103/E (题目链接) 题意 给出$n$个数,每个数与一个集合相关联.从其中选出最小的若干个数,选出的数的个数与这些 ...
- Elasticsearch基础知识要点QA
前言:本文为学习整理实践他人成果的记录型博客.在此统一感谢各原作者,如果你对基础知识不甚了解,可以通过查看Elasticsearch权威指南中文版, 此处注意你的elasticsearch版本,版本不 ...
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- 一个程序如何在调试时退出调试或退出while循环
1.退出调试 按Ctrl+C 2.退出while循环 比如 #include <stdio.h> #include <stdlib.h> int main() { long a ...
- js中if()条件中变量为false的情况
<html> <head> <script type="text/javascript" src="jquery-3.1.1.min.js& ...
- Jenkins-Pipeline 流水线发布部署项目
node { sh 'mkdir -p cms' dir('cms') { git branch: 'prerelease', credentialsId: '5fb79ef0-4301-4b7c-a ...
- linux反向删除文件
Linux反选删除文件 最简单的方法是 # shopt -s extglob (打开extglob模式) # rm -fr !(file1) 如果是多个要排除的,可以这样: # rm -r ...
- CM记录-JVM调优
1.堆栈大小 2.JVM重用 3.GC
- 矩阵乘法np.dot()及np.multipy()区别
1. 线性代数中矩阵乘法: np.dot() import numpy as np # 2 x 3 matrix1 = np.array([[1, 2, 3], [4, 5, 6]]) # 3 ...
- linux 命令收集 阿里云nginx升级等 查看磁盘空间 版本等
—————————————————— 查磁盘 df -h此命令直观的呈现出磁盘大小有多少Gdf -hl文件系统 容量 已用 可用 已用% 挂载点/dev/hdb2 75G 75G 0 100% /就是 ...