题意:给定一棵有n个结点的树,每一个点有一个权值。共同拥有m个询问。对于每一个询问(u,v,k),回答结点u至v之间第k小的点的权值。

思路:主席树+lca。首先指定一个根结点dfs一次并在此过程中建好主席树。对于对于每一个询问,我们仅仅须要考虑四棵树,即T[u], T[v], T[lca(u,v)], 再加上T[fa( lca(u,v) )],fa( lca(u,v) )表示lca(u, v)的父亲结点。

这样一来问题就和线性序列里第k小的数一样了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; //const int maxn = 100000 + 100;
//const int INF = 0x3f3f3f3f; const int maxn = 100000+10000;
const int M = 2000000;
int n, q, m, tot;
int t[maxn], w[maxn], fa[maxn];
int T[maxn], lson[M], rson[M], c[M]; struct Quest {
int l, r, k;
} quest[maxn]; void Init_hash(int k) {
sort(t, t+k);
m = unique(t, t+k) - t;
} int Hash(int x) {
return lower_bound(t, t+m, x) - t;
} int build(int l, int r) {
int root = tot++;
c[root] = 0;
if(l != r) {
int mid = (l+r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid+1, r);
}
return root;
} int Insert(int root, int pos, int val) {
int newroot = tot++, tmp = newroot;
int l = 0, r = m-1;
c[newroot] = c[root] + val;
while(l < r) {
int mid = (l+r)>>1;
if(pos <= mid) {
lson[newroot] = tot++; rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r = mid;
}
else {
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid+1;
}
c[newroot] = c[root] + val;
}
return tmp;
} int Query(int l_root, int r_root, int lca, int k) {
int l = 0, r = m -1, lca_root = T[lca], fa_root = fa[lca];
while(l < r) {
int mid = (l+r) >> 1;
int tmp = c[lson[l_root]]+c[lson[r_root]]-c[lson[lca_root]]-c[lson[fa_root]];
if(tmp >= k) {
r = mid;
l_root = lson[l_root]; r_root = lson[r_root]; lca_root = lson[lca_root]; fa_root = lson[fa_root];
}
else {
l = mid + 1;
k -= tmp;
l_root = rson[l_root]; r_root = rson[r_root]; lca_root = rson[lca_root]; fa_root = rson[fa_root];
}
}
return l;
} int pnt[maxn], lca[maxn];
bool vis[maxn];
vector<int> G[maxn], query[maxn], num[maxn];
int find(int x) {
if(x == pnt[x]) return x;
return pnt[x] = find(pnt[x]);
}
void dfs_lca(int u) {
vis[u] = 1; pnt[u] = u;
int sz1 = G[u].size();
for(int i = 0; i < sz1; i++) {
int v = G[u][i];
if(vis[v]) continue;
fa[v] = T[u];
dfs_lca(v);
pnt[v] = u;
}
int sz2 = query[u].size();
for(int i = 0; i < sz2; i++) {
int v = query[u][i];
if(vis[v]) lca[num[u][i]] = find(v);
}
}
void init() {
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++) {
G[i].clear();
query[i].clear();
num[i].clear();
}
} void dfs_ZXTree(int cur, int fa) {
int sz = G[cur].size();
for(int i = 0; i < sz; i++) {
int u = G[cur][i];
if(u == fa) continue;
T[u] = Insert(T[cur], Hash(w[u]), 1);
dfs_ZXTree(u, cur);
}
} int main() {
//freopen("input.txt", "r", stdin);
while(cin >> n >> q) {
init();
m = 0; tot = 0;
for(int i = 1; i <= n; i++) scanf("%d", &w[i]), t[m++] = w[i];
Init_hash(m);
build(0, m-1);
for(int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
T[1] = Insert(T[0], Hash(w[1]), 1);
dfs_ZXTree(1, -1);
for(int i = 0; i < q; i++) {
int l, r, k; scanf("%d%d%d", &l, &r, &k);
quest[i].l = l; quest[i].r = r; quest[i].k = k;
query[l].push_back(r); query[r].push_back(l);
num[l].push_back(i); num[r].push_back(i);
}
fa[1] = T[0];
dfs_lca(1);
for(int i = 0; i < q; i++) {
printf("%d\n", t[Query(T[quest[i].l], T[quest[i].r], lca[i], quest[i].k)]);
}
}
return 0;
}




SPOJ 10628 Count on a tree (lca+主席树)的更多相关文章

  1. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  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. bzoj 2588 Spoj 10628. Count on a tree(主席树)

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

  4. bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】

    算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...

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

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

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

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

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

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

  8. Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...

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

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

  10. Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...

随机推荐

  1. 自己动手丰衣足食,为Zepto添加Slide动画效果

    一.缘由 公司的移动端项目,采用zepto为主要框架,但是zepto毕竟是精简版的jquery,体积小了,功能自然没有这么强大,特别是动画和选择器这两块,需要我们自己去拓展. 在项目开发过程中,很多页 ...

  2. GYM 100741A Queries(树状数组)

    A. Queries time limit per test 0.25 seconds memory limit per test 64 megabytes input standard input ...

  3. MySQL实现递归查询

    DROP FUNCTION IF EXISTS queryChildrenCaseInfo;CREATE FUNCTION queryChildrenCaseInfo(cId INT)RETURNS ...

  4. 在PL/SQL中使用带参数的游标

    需求:查询并输出部门名称为SALES的员工信息 SET serveroutput ON; DECLARE CURSOR c_emp(paramName VARCHAR2) IS SELECT * FR ...

  5. amcharts简单demo(仪表盘)

    最近项目中展示数据有用到amcharts,一个小demo例子. <script src="<%=basePath%>amchart/amcharts.js" ty ...

  6. javascript中计算点击多少次

    点击事件:onclick <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  7. 手动触发dom节点事件代码

    在爬代码过程中,碰到一个稀奇古怪的问题.需要手工修改select的值,然后手动触发select的change事件,但使用网络上查到的通过trigger.onchange()事件触发都不执行,没办法,只 ...

  8. CDC之fast->slow (1)

    Sampling slower signals into faster clock domains causes fewer potential problems than sampling fast ...

  9. SQL Server存储过程作业(一)

    创建客房类型表RoomType 创建客房状态表RoomState 创建客房信息表Room 创建结账状态表ResideState 创建客人信息表GuestRecord 编写sql语句 USE maste ...

  10. WCF分佈式事務支持

    WCF分佈式事務對Binding有要求,不支持BasicHttpBinding,BasicHttpContextBinding,NetPeerTcpBinding 要支持分佈式事務,需要進行以下配置: ...