洛谷P2633 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
暴力自重。。。
来源:bzoj2588 Spoj10628.
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
树上第$k$大问题
做法比较套路
首先对权值离散化。
然后对每个节点建主席树,从父亲那里拷贝历史版本
求LCA的话用树剖,顺便可以建主席树。
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=*1e6+;
const int INF=1e8+;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
struct Edge
{
int u,v,nxt;
}E[MAXN];
int head[MAXN];
int num=;
inline void AddEdge(int x, int y)
{
E[num].u = x;
E[num].v = y;
E[num].nxt = head[x];
head[x] = num++;
}
int a[MAXN], b[MAXN], N, M, root[MAXN], totnum;
int deep[MAXN], son[MAXN], top[MAXN], fa[MAXN], tot[MAXN];
struct node
{
int ls, rs, w;
}T[MAXN];
void Insert(int pre,int &now,int ll,int rr,int val)
{
now=++totnum;
T[now].ls=T[pre].ls;T[now].rs=T[pre].rs;
T[now].w=T[pre].w+;
if(ll==rr) return ;
int mid=ll+rr>>;
if(val<=mid) Insert(T[pre].ls,T[now].ls,ll,mid,val);
else Insert(T[pre].rs,T[now].rs,mid+,rr,val);
}
void dfs1(int now, int f)
{
fa[now] = f;
Insert(root[f],root[now],,N,a[now]);
tot[now] = ;
int maxson=-;
for(int i = head[now]; i != -; i = E[i].nxt)
{
if(deep[E[i].v] == && E[i].v != f)
{
deep[E[i].v] = deep[now] + ;
dfs1(E[i].v, now);
tot[now] += tot[E[i].v];
if(tot[E[i].v]>maxson) maxson = tot[E[i].v],son[now] = E[i].v;
}
}
}
void dfs2(int now, int topf)
{
top[now] = topf;
if(!son[now]) return ;
dfs2(son[now], topf);
for(int i = head[now]; i != -; i=E[i].nxt)
if(E[i].v != son[now] && E[i].v != fa[now])
dfs2(E[i].v, E[i].v);
}
int LCA(int x, int y)
{
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x,y);
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x,y);
return x;
}
int Query(int x, int y, int lca, int falca, int ll, int rr, int k)
{
if(ll==rr) return ll;
int used=T[T[x].ls].w + T[T[y].ls].w - T[T[lca].ls].w - T[T[falca].ls].w;
int mid=ll+rr>>;
if(k<=used) return Query(T[x].ls, T[y].ls, T[lca].ls, T[falca].ls, ll, mid, k);
else return Query(T[x].rs, T[y].rs, T[lca].rs, T[falca].rs, mid+, rr, k-used);
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-,sizeof(head));
N = read(); M = read();
for(int i = ; i<=N; i++) a[i] = b[i] = read();
sort(b+, b+N+);
int num = unique(b, b+N+) - b - ;
for(int i = ; i<=N; i++) a[i]=lower_bound(b, b+N, a[i]) - b;
for(int i=; i<=N-; i++)
{
int x=read(), y=read();
AddEdge(x, y);
AddEdge(y, x);
}
deep[] = ;
dfs1(, );
dfs2(,);
int lastans=;
while(M--)
{
int x=read(),y=read(),k=read();
x=x^lastans;
int lca=LCA(x,y);
lastans=b[Query(root[x], root[y], root[lca], root[fa[lca]],,N,k)];
printf("%d\n",lastans);
}
return ;
}
洛谷P2633 Count on a tree的更多相关文章
- 洛谷 P2633 Count on a tree
P2633 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中last ...
- 洛谷P2633 Count on a tree(主席树上树)
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷 P2633 Count on a tree 主席树
在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$ ,建立 $i$ 到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...
- 洛谷 P2633 Count on a tree 题解
题面 对于每个点建立一颗主席树: 然后按照树上差分的思想统计主席树的前缀和: lca+主席树+前向星存表就可以了: #include <bits/stdc++.h> #define inc ...
- ☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...
- 洛谷P2633 Count on a tree 主席树
传送门:主席树 解题报告: 传送门! umm这题我还麻油开始做 所以 先瞎扯一波我的想法,如果错了我就当反面教材解释这种典型错误,对了我就不管了QwQ 就直接dfs,在dfs的过程中建树 然后就直接查 ...
- 洛谷 P6177 - Count on a tree II/【模板】树分块(树分块)
洛谷题面传送门 好家伙,在做这道题之前我甚至不知道有个东西叫树分块 树分块,说白了就是像对序列分块一样设一个阈值 \(B\),然后在树上随机撒 \(\dfrac{n}{B}\) 个关键点,满足任意一个 ...
随机推荐
- mysql 密码的破解
现在的主流的数据库一般是mysql ,sql server , oracle. 有的时候我们忘记了数据库密码的时候我们要怎么办,破解别人的数据库的密码的时候我们要怎么搞 忘记密码是一件很头痛的 ...
- OpenJDK源码研究笔记(三)-RandomAccess等标记接口的作用
标识接口是没有任何方法和属性的接口. 它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情. 下面来看一个标记接口RandomAccess. public interface Rando ...
- 【codeforces 816A】Karen and Morning
[题目链接]:http://codeforces.com/contest/816/problem/A [题意] 让你一分钟一分钟地累加时间; 问多长时间以后是个回文串; [题解] reverse之后如 ...
- Springmvc JSON交互
先上前端javascript.ajax代码 <pre name="code" class="javascript"> function testAj ...
- 9、包、访问控制、import、static、static代码块、final、抽象类、接口、instanceof、多态
1.包 三级命名:公司的尾缀(com).公司名字(baidu).业务(Sale) java.lang:默认包:String.Math,Object,System java.util:工具包 java. ...
- ural 1143. Electric Path(凸包上最短哈密顿路径)
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1143 题意:逆时针给一个凸包的n(n<=200)个顶点坐标,求一个最短哈密顿路径的 ...
- hdu4089Activation 概率dp
//一条队列对于第一个人的情况 //概率p1:队列保持不变 //p2:第一个人到队尾 //p3:第一个人出队 //p4:系统崩溃 //队列中有N个人,Tomato 在第M位置,求系统崩溃.Tomato ...
- iOS 中client和server的 Web Service 网络通信 (1)
当你打开你手机上新浪微博应用或者知乎应用是.你是否会去想这些显示在手机上的图片和数据时从哪里来的?又是通过如何的方法实现的?好.那么接下来就介绍是如何实现的.过程又是怎么样的. 当我们浏览着 ...
- C&C控制服务的设计和侦测方法综述——DDoS攻击,上传从宿主机偷窃的到的信息,定时给感染机文件加密勒索等。
这篇文章总结了一些我在安全工作里见到过的千奇百怪的C&C控制服务器的设计方法以及对应的侦测方法,在每个C&C控制服务先介绍黑帽部分即针对不同目的的C&C服务器设计方法,再介绍白 ...
- ARM嵌入式复习
第一章 1.嵌入式系统 “以应用为中心,以计算机技术为基础,软硬件可裁剪,适用于应用系统对功能,可靠性,成本,体积,功耗要求严格的专用计算机系统” 根据应用的要求,沿着“体积小,低功耗,高可靠”方向发 ...