洛谷P2633/bzoj2588 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行,表示每个询问的答案。

输入输出样例

输入样例#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.

Solution

bzoj题面传送门

无修改,树上路径查询k小值

k小值可以主席树解决,树上路径其实不用真的提出来,我们可以运用差分的思路,由于是点差,求出它的\(lca,\)那么\(ans=a[u]+a[v]-a[lca]-a[fa[lca]]\).

具体到这道题就是\(u\)的主席树\(+v\)的主席树\(-lca\)的主席树\(-fa[lca]\)的主席树

\(lca\)倍增求就可以了

Code

#include<bits/stdc++.h>
#define in(i) (i=read())
#define il extern inline
#define rg register
#define mid ((l+r)>>1)
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lol long long
using namespace std; const int N=1e5+10; int read() {
int ans=0, f=1; char i=getchar();
while (i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while (i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48), i=getchar();
return ans*f;
} int n,m,cur,num,tot,pre;
int head[N],nex[N<<1],to[N<<1];
int f[25][N],lg[N]={-1},dep[N];
int a[N],h[N],rt[N<<6]; struct Chair_Tree {
int l,r,v;
}t[N<<6]; void add(int a,int b) {
to[++cur]=b,nex[cur]=head[a],head[a]=cur;
to[++cur]=a,nex[cur]=head[b],head[b]=cur;
} void insert(int &u,int l,int r,int pre,int p) {
t[u=++tot]=t[pre], t[u].v++;
if(l==r) return;
if(p<=mid) insert(t[u].l,l,mid,t[pre].l,p);
else insert(t[u].r,mid+1,r,t[pre].r,p);
} int query(int a,int b,int c,int d,int l,int r,int k) {
int AQ=t[t[a].l].v+t[t[b].l].v-t[t[c].l].v-t[t[d].l].v;
if(l==r) return h[l];
if(k<=AQ) return query(t[a].l,t[b].l,t[c].l,t[d].l,l,mid,k);
else return query(t[a].r,t[b].r,t[c].r,t[d].r,mid+1,r,k-AQ);
} void dfs(int u) {
a[u]=lower_bound(h+1,h+1+num,a[u])-h;
insert(rt[u],1,num,rt[f[0][u]],a[u]);
for (int i=head[u];i;i=nex[i]) {
if(to[i]==f[0][u]) continue;
dep[to[i]]=dep[u]+1, f[0][to[i]]=u;
dfs(to[i]);
}
} void init() {
for (int i=1;i<=n;i++) lg[i]=lg[i>>1]+1;
for (int i=1;i<=lg[n];i++)
for (int j=1;j<=n;j++)
f[i][j]=f[i-1][f[i-1][j]];
} int LCA(int a,int b) {
if(dep[a]>dep[b]) swap(a,b);
int s=dep[b]-dep[a];
for (int i=lg[s];i>=0;i--)
if(s>>i&1) b=f[i][b];
if(a==b) return a;
for (int i=lg[n];i>=0;i--) {
if(f[i][a]==f[i][b]) continue;
a=f[i][a], b=f[i][b];
}return f[0][a];
} int main()
{
in(n), in(m);
for (int i=1;i<=n;i++) in(a[i]),h[i]=a[i];
sort(h+1,h+1+n); num=unique(h+1,h+1+n)-h-1;
for (int i=1,x,y;i<n;i++) in(x),in(y),add(x,y);
dep[1]=1, dfs(1), init();
for (int i=1,a,b,k;i<=m;i++) {
in(a),in(b),in(k),a^=pre;
int lca=LCA(a,b);
printf("%d\n",pre=query(rt[a],rt[b],rt[lca],rt[f[0][lca]],1,num,k));
}
}

洛谷P2633/bzoj2588 Count on a tree (主席树)的更多相关文章

  1. 【洛谷 P2633】 Count on a tree(主席树,树上差分)

    题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...

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

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

  3. BZOJ2588:Count on a tree(主席树)

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

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

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

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

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

  6. 【洛谷2633】Count on a tree(树上主席树)

    点此看题面 大致题意: 给你一棵树,每次问你两点之间第\(k\)小的点权,强制在线. 主席树 这种题目强制在线一般就是数据结构了. 而看到区间第\(k\)小,很容易就能想到主席树. 至少不会有人想到树 ...

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

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

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

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

  9. P2633 Count on a tree(主席树)

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

随机推荐

  1. Java接口获取系统配置信息

    Java获取当前运行系统的配置信息 接口:System.getProperty() 参数 描述 java.version Java运行时环境版本 java.vendor Java运行时环境供应商 ja ...

  2. DNS递归查询与迭代查询

    注:一般TCP/IP的应用层或者OSI的会话.表示.应用层把数据称为数据或者信息,到了传输层把数据称为报文,到了最底层就是比特流了也就是字节流 DNS递归查询与迭代查询   基础知识 1.域名系统 2 ...

  3. JAVA学习笔记--策略设计模式与适配器模式

    一.策略设计模式 创建一个能够根据所传递对象的不同而具有不同行为的方法被称为策略设计模式:这类方法包含所要执行的算法中固定不变的部分,而“策略”包含变化的部分.策略就是传递进去的参数对象,它包含要执行 ...

  4. Hyperledger Fabric中的Identity

    Hyperledger Fabric中的Identity 什么是Identity 区块链网络中存在如下的角色:peers, orderers, client application, administ ...

  5. 微信小程序-----自定义验证码实现

    这一段时间做小程序项目,使用的是mpvue的框架,需要自己实现验证码输入,模拟input的光标,上一个框输入后后一个框自动获取焦点,删除时从后往前依次删除.下图是整体效果: <template& ...

  6. 大数据-storm学习资料视频

    storm学习资料视频 https://pan.baidu.com/s/18iQPoVFNHF1NCRBhXsMcWQ

  7. ES6的新特性(1)——ES6 的概述

    ES6 的概述 首先,感谢马伦老师的ES6新特性的教程. ECMAScript 和 JavaScript 的关系是 ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前 ...

  8. ionic 开发实例

    ionic 开发实例 一.ionic初始化项目 1:安装ionic npm install -g ionic 2:初始化项目框架 我们可以用命令创建一个应用程序,可以使用我们的一个现成的应用程序模板, ...

  9. 【Alpha】阶段第二次Scrum Meeting

    [Alpha]阶段第二次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 发表评论接口 更新评论接口 赵智源 部署实际项目 编写脚本实现持续集成 肖萌威 编写注册 ...

  10. Python 变量和常量及数据类型

    一.变量的命名 变量由字母.数字和下划线组成.变量的第1个字符必须是字母或下划线. 二.变量的赋值 例: x = 1 三.局部变量 局部变量只能在函数或者代码段内使用. 四.全局变量 在函数之外定义的 ...