洛谷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导入Sql文件时报Error Code: 2013 - Lost connection to MySQL server during query
MySql 有时我们导入sql文件,文件过大,导致Error Code: 2013 - Lost connection to MySQL server during query这种错误 执行以下: S ...
- 收集整理的openstack java封装 api的第三方实现的选择
Apache jclouds 地址:http://jclouds.apache.org/guides/openstack/ 一个开源库,java实现,支持cloudstack,openstack以及各 ...
- 不安装Oracle客户端,用plsql连接远程Oracle数据库(绝对解决你的问题)
1,首先准备下载两个软件,一个是instantclient.zip,另一个是plsql安装包.但是得确定您的电脑是32位还是64位,我这边提供了32位和64位的供您下载: 百度网盘:https://p ...
- Mahout推荐算法API具体解释【一起学Mahout】
阅读导读: 1.mahout单机内存算法实现和分布式算法实现分别存在哪些问题? 2.算法评判标准有哪些? 3.什么会影响算法的评分? 1. Mahout推荐算法介绍 Mahout推荐算法,从数据处理能 ...
- swift学习笔记(五)构造过程
构造过程是为了使用某个类.结构体或枚举类型的实例而进行的准备过程.在构造过程中,对每一个属性进行了初始值预设和其它必要的准备和初始化工作. 与OC相比,swift的构造函数.不须要返回值.同一时候,在 ...
- APP-午饭去哪吃
走到这个快节奏的城市中.部门聚餐.朋友吃饭这些都是日常生活中时有发生的事情,往往吃的东西都是千篇一律,图的也仅仅剩下的是环境了.那么.非常纠结常常去的地方,怎么办呢?来吧.我们随机摇一个吧! wate ...
- 智课雅思词汇---十、pend是什么意思
智课雅思词汇---十.pend是什么意思 一.总结 一句话总结:[词根含义]:悬挂,垂;称量;支付 词根:-pend-, -pens- [词根含义]:悬挂,垂;称量;支付 [词根来源]:来源于拉丁语动 ...
- js中如何取精度
js中如何取精度 一.总结 一句话总结:其实round()函数去经度会有误差,直接用num.toFixed(2)简单方便. toFixed()方法会按照指定的小数返回数值的字符串表示.var num ...
- django 笔记17 ModelForm
Model 数据库操作 验证 验证 Form -class LoginForm(Form): email = fields.EmailField() is_valid 每一个字段进行正则(字段内置正则 ...
- 实时监控Cat之旅~对请求是否正常结束做监控(分布式的消息树)
对基于请求的分布式消息树的分析 在MVC时有过滤器System.Web.Mvc.ActionFilterAttribute,它可以对action执行的整个过程进行拦截,执行前与执行后我们可以注入自己的 ...