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;
}

转载于:https://www.cnblogs.com/Mychael/p/8282799.html

BZOJ2588 Count on a tree 【树上主席树】相关推荐

  1. BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

    BZOJ 2588 Count on a tree 题面 求树上两点之间路径上第k大的点权. 题解 一开始看到这道题觉得是树剖,然后又听说是主席树,然后以为是主席树+树剖,差点没吓死-- 然后发现,如 ...

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

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

  3. 【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA

    传送门 写在前面:一天下来就写了两道主席树的题--(codevs上的一道智障天梯不算) 思路: 才知道原来主席树不仅可以通过dfs序维护子树区间,还可以直接维护一条到根的链-- 我们建好主席树后,每次 ...

  4. SPOJ - COT Count on a tree [LCA+主席树]【数据结构】

    题目链接:http://www.spoj.com/problems/COT/en/ -------------------------------------- COT - Count on a tr ...

  5. SPOJ - COT Count on a tree(LCA+主席树+离散化)

    题目链接:点击查看 题目大意:给出一棵树,每个点都有一个权值,现在给出m个询问,每次询问的格式是u,v,k,要求输出u-v这条路径上第k大的数 题目分析:一看到第k大的数就会想到主席树,既然是在树上的 ...

  6. SPOJ COT Count on a tree(主席树+倍增lca)

    思路:这个题其实就是树上的第k小,主席树的本质还是类似于前缀和一样的结构,所以是完全相同的,所以我们在树上也可以用同样的方法,我们对于每一个节点进行建树,然后和普通的树上相同,ab之间的距离是等于 r ...

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

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

  8. 【牛客】树的距离 树上主席树

    [牛客]树的距离 树上主席树 题意 思路 Code(709MS) 传送门: 题意 给 一 颗 树 , 求 以 x 为 子 树 中 , 距 离 x 大 于 等 于 k 的 点 与 x 的 距 离 和 . ...

  9. BZOJ2588 Count on a tree DFS序+LCA+值域主席树

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

最新文章

  1. 寒假每日一题(入门组)【week3 完结】
  2. mysql的一些初步使用!mysqlcheck mysqladmin 建立删除修改表,库,等
  3. web.config连接mysql_web.config中配置数据库连接的方式
  4. C语言课后习题(30)
  5. python基础教程多少页_看完这篇文章,你的Python基础就差不多了(附200页《Python400集》)...
  6. Go36-32-context.Context
  7. 关于蛙跳算法的计算机文献,文化蛙跳算法性能分析研究.PDF
  8. Linux安装和卸载JDK
  9. android点击监听,android基础之点击监听器的2种监听实现
  10. python服务器搭建nginx_从0开始在腾讯云服务器上搭建python3+flask+uwsgi+nginx服务器...
  11. 2020美赛F题翻译
  12. 学了C语言,能开发什么项目?
  13. web前端html+css实现立体旋转相册(表白可用)
  14. 【Android】虚拟环绕声
  15. Vivo升级android版本,vivo手机系统怎么升级?vivo系统升级教程
  16. 03_JavaScript常见运算符
  17. 高级宏观经济学公式整理
  18. 明星热图|童瑶、万茜、周冬雨、宁静、吴昕、宋威龙、李荣浩等签约新品牌...
  19. 关于、、的含义及区别
  20. c语言数据结构-遍历

热门文章

  1. 北京钛谷诚泽网络通讯科技有限公司
  2. 手机app 有没有window.location.href_热议小程序使用场景越来越多,未来有没有可能替代手机APP?...
  3. 如何用计算机弹逆战6,逆战星光弹夹使用方法介绍 轻松玩转星光弹
  4. .net 返回datatable显示sql列名_3汇总分析-SQL
  5. linux make链接.o文件,Linux操作系统至gcc编译器、makefile
  6. nc65语义模型设计_完整word版,NC数据加工做语义模型
  7. java 基本的数据类型_Java的基本数据类型介绍
  8. 835 由于安全层无法对远程计算机进行身份验证_干货 | 看黑客都是这样远程桌面安全设置...
  9. 2.innodb后台线程
  10. GetSystemMetrics()函数的用法