2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB

Submit: 7577  Solved: 1852

[Submit][Status][Discuss]

Description

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

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。最后一个询问不输出换行符

Sample Input

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

Sample Output

2

8

9

105

7

HINT




HINT:
N,M<=100000
暴力自重。。。

求区间第K大问题一般使用主席树

首先我们要了解主席树具有查询部分数据的功能,我们只要找出一种建树顺序,使得我们能通过区间加减拼凑出我们的目标序列

我们进行一次dfs,每个节点u以其father版本树建树,这样子每个节点所对应的主席树储存着该节点到根的数据

我们要得到u,v两点之间的数据,就rt[u] + rt[v] - rt[lca] - rt[fa[lca]]就好了【自己脑补】

【md调了两个小时原来是离散化出了错误,不知道为什么同种权值不能编一个号,求dalao解答QAQ】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 100005,maxm = 4000005,INF = 1000000000;
inline LL RD(){
LL out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N,M,A[maxn],id[maxn],V[maxn],H[maxn],dep[maxn],fa[maxn][20],n = 0;
int siz = 0,rt[maxn],pos;
int head[maxn],nedge = 0;
struct EDGE{int to,next;}edge[2 * maxn];
struct node{LL sum;int ls,rs;}e[maxm];
inline void add(int u,int v){
edge[nedge] = (EDGE){v,head[u]}; head[u] = nedge++;
edge[nedge] = (EDGE){u,head[v]}; head[v] = nedge++;
}
inline bool cmp(const int& a,const int& b){return A[a] < A[b];}
void build(int& u,int pre,int l,int r){
u = ++siz; e[u] = e[pre]; e[u].sum++;
if (l == r) return;
int mid = l + r >> 1;
if (mid >= pos) build(e[u].ls,e[pre].ls,l,mid);
else build(e[u].rs,e[pre].rs,mid + 1,r);
}
int Query(int r1,int r2,int r3,int r4,int l,int r,int k){
if (l == r) return l;
int mid = l + r >> 1,temp = e[e[r1].ls].sum + e[e[r2].ls].sum - e[e[r3].ls].sum - e[e[r4].ls].sum;
if (temp >= k) return Query(e[r1].ls,e[r2].ls,e[r3].ls,e[r4].ls,l,mid,k);
else return Query(e[r1].rs,e[r2].rs,e[r3].rs,e[r4].rs,mid + 1,r,k - temp);
}
inline int Lca(int u,int v){
if (dep[u] < dep[v]) swap(u,v);
int d = dep[u] - dep[v];
for (int i = 0; (1 << i) <= d; i++)
if ((1 << i) & d) u = fa[u][i];
if (u == v) return u;
for (int i = 19; i >= 0; i--)
if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
return fa[u][0];
}
void dfs(int u,int f,int d){
fa[u][0] = f; pos = V[u]; dep[u] = ++d;
build(rt[u],rt[f],1,n);
Redge(u) if (edge[k].to != f) dfs(edge[k].to,u,d);
}
void init2(){REP(i,19) REP(u,N) fa[u][i] = fa[fa[u][i - 1]][i - 1];}
void init(){
memset(head,-1,sizeof(head));
N = RD(); M = RD();
REP(i,N) A[i] = RD(),id[i] = i;
REP(i,N - 1) add(RD(),RD());
sort(id + 1,id + 1 + N,cmp);
V[id[1]] = ++n; H[n] = A[id[1]];
for (int i = 2; i <= N; i++) V[id[i]] = ++n,H[n] = A[id[i]];
}
void solve(){
int u,v,k,lca,last = 0;
while (M--){
u = last ^ RD(); v = RD(); k = RD(); lca = Lca(u,v);
printf("%d",last = H[Query(rt[u],rt[v],rt[lca],rt[fa[lca][0]],1,n,k)]);
if (M) printf("\n");
}
}
int main(){
init();
dfs(1,0,0);
init2();
solve();
return 0;
}

BZOJ2588 Count on a tree 【树上主席树】的更多相关文章

  1. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  2. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  3. [Bzoj2588]Count on a tree(主席树+LCA)

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

  4. [BZOJ2588]Count on a tree(LCA+主席树)

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

  5. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  6. BZOJ2588 SPOJ10628 Count on a tree 【主席树】

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

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

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

  8. 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树

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

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

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

  10. 【bzoj2588/P2633】count on a tree —— LCA + 主席树

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

随机推荐

  1. 角色 RESOURCE、CONNECT、DBA具有的权限

    角色 RESOURCE.CONNECT.DBA具有的权限 select grantee,privilege from dba_sys_privs where grantee='RESOURCE' or ...

  2. 「日常训练」Regular Bridge(Codeforces Round 306 Div.2 D)

    题意与分析 图论基础+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #defi ...

  3. uvaoj1585Score(暴力)

    1585 ScoreThere is an objective test result such as “OOXXOXXOOO”. An ‘O’ means a correct answer of a ...

  4. C++ 基础面试题-1

    请说出下面代码在32位系统下的输出内容 /* ** 2018/03/21 21:43:00 ** Brief: ** Author:ZhangJianWei ** Email:Dream_Dog@16 ...

  5. JMeter自学笔记2-图形界面介绍

    一.写在前面的话: 上篇我们已经学会了如何安装JMeter和打开JMeter,那么这篇我们将对JMeter的图形界面做一个简单的介绍.大家只要简单的了解即可,无需死记硬背,在今后的学习和使用中慢慢熟悉 ...

  6. 缓存 memcache 小白笔记

    W: Memcached是神魔? Q:Memcached是一个自由开源的,高性能,分布式内存对象缓存系统. W:原理图 Q:如下 1浏览器    2 服务器   3  数据库    4  memcac ...

  7. 关于java使用double还是float

    眼睛一亮在论坛上发现一枚很有价值的评论赶紧抄下来... 记住java一定要用double,更鼓不变,就算数值不大也要用double.了解java虚拟机的底层会知道,float放在内存中其实是当作dou ...

  8. 【第一章】MySQL数据概述

    安装部署 备份恢复主备复制读写分离HA架构分布式数据库压力测试性能优化自动化运维 ==数据的存储方式1. 人工管理阶段2. 文件系统阶段3. 数据库系统管理阶段 ==数据库技术构成1. 数据库系统 D ...

  9. 官方文档 恢复备份指南三 Recovery Manager Architecture

    本节讨论以下问题: About the RMAN Environment                        关于RMAN环境 RMAN Command-Line Client        ...

  10. selenium中的三种等待方式(显示等待WebDriverWait()、隐式等待implicitly()、强制等待sleep())---基于python

    我们在实际使用selenium或者appium时,等待下个等待定位的元素出现,特别是web端加载的过程,都需要用到等待,而等待方式的设置是保证脚本稳定有效运行的一个非常重要的手段,在selenium中 ...