题目描述

给定一棵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行,表示每个询问的答案。

输入输出样例

输入样例#1: 复制

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
输出样例#1: 复制

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的更多相关文章

  1. 洛谷 P2633 Count on a tree

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

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

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

  3. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  4. 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  5. 洛谷 P2633 Count on a tree 主席树

    在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$  ,建立 $i$  到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...

  6. 洛谷 P2633 Count on a tree 题解

    题面 对于每个点建立一颗主席树: 然后按照树上差分的思想统计主席树的前缀和: lca+主席树+前向星存表就可以了: #include <bits/stdc++.h> #define inc ...

  7. ☆ [洛谷P2633] Count on a tree 「树上主席树」

    题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...

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

    传送门:主席树 解题报告: 传送门! umm这题我还麻油开始做 所以 先瞎扯一波我的想法,如果错了我就当反面教材解释这种典型错误,对了我就不管了QwQ 就直接dfs,在dfs的过程中建树 然后就直接查 ...

  9. 洛谷 P6177 - Count on a tree II/【模板】树分块(树分块)

    洛谷题面传送门 好家伙,在做这道题之前我甚至不知道有个东西叫树分块 树分块,说白了就是像对序列分块一样设一个阈值 \(B\),然后在树上随机撒 \(\dfrac{n}{B}\) 个关键点,满足任意一个 ...

随机推荐

  1. 洛谷P4994 终于结束的起点

    希望是这道题的第一篇题解,并且真的做到了! upd 2018/11/4:规律补锅,让代码更加易懂 本来月赛时想打个表,打到一半,发现\(n\)稳定在\(m\)附近? 题目的意思是\(n < m ...

  2. 【BZOJ 1059】[ZJOI2007]矩阵游戏

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 最后要求对于所有的i,a[i][i]=1 那么,如果第i行的第j列为1. 就说明我们可以把这个第i行换到第j行. 因为这样的话,a[ ...

  3. Java 学习(11): 面向对象编程—继承(super,this)

    Java 继承 what: 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为.子类从它的父类中继承可访问的数据域和方法,也 ...

  4. Docker_入门?只要这篇就够了!(纯干货适合0基础小白)

    与sgy一起开启你的Docker之路 关键词: Docker; mac; Docker中使用gdb无法进入断点,无法调试; 更新1: 看起来之前那一版博文中参考资料部分引用的外站链接太多,被系统自动屏 ...

  5. 安装spark问题汇总

    使用的版本是 spark-1.6.3-bin-without-hadoop 运行spark-shell报错 运行spark-sql报错找不到org.datanucleus.api.jdo.JDOPer ...

  6. Qt之布局管理器

    简述 Qt的布局系统提供了一个简单的和强有力的方式,来自动排列窗口子控件布局. 所有QWidget子类可以使用布局来管理他们的子控件.QWidget::setLayout()函数可以为一个控件布局.当 ...

  7. [Javascript] Improve Composition with the Compose Combinator

    To make our composition more readable and easier to name we are going to ceate a compose function we ...

  8. Java数据库訪问小结

    </pre>1.JDBC訪问方法</p><p></p><p>DBHelper类訪问数据库.Dao类写数据訪问,View类进行应用,初学实例图 ...

  9. Android学习路线(十二)Activity生命周期——启动一个Activity

    DEMO下载地址:http://download.csdn.net/detail/sweetvvck/7728735 不像其他的编程模式那样应用是通过main()函数启动的.Android系统通过调用 ...

  10. 漫谈linux之文件IO篇(SSD写性能和机械硬盘差不多,读是4到10倍)

    前同事的文章,觉得写得很清晰,收藏了. http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的东西,技术 ...