bzoj  2588: Spoj 10628. Count on a tree

http://www.lydsy.com/JudgeOnline/problem.php?id=2588

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
暴力自重。。。

Source

鸣谢seter

数据结构:主席树

辅助算法:LCA

以点的dfs序为下标,以点权为区间建立主席树

以前做过的主席树在序列上,所以是以前一个节点的线段树为基准建立的

这里在树上,所以可以考虑以根为基准建立线段树

u,v间增加的点数=cnt[u]+cnt[v]-cnt[LCA(u,v)]-cnt[father[LCA(u,v)]]

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
struct count
{private:struct node{int l,r,cnt;}tr[N*20];struct data {int to,next;}e[N*2];int n,m,a[N],head[N],edge_cnt;int dep[N],son[N],f[N],bl[N],sz;int root[N],cntt,hash[N],hash_tot;int last;public:inline int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}        return x*f;}inline void add(int u,int v){e[++edge_cnt].to=v;e[edge_cnt].next=head[u];head[u]=edge_cnt;e[++edge_cnt].to=u;e[edge_cnt].next=head[v];head[v]=edge_cnt;}void init(){n=read();m=read();for(int i=1;i<=n;i++) a[i]=read(),hash[i]=a[i];int u,v;for(int i=1;i<n;i++){scanf("%d%d",&u,&v);add(u,v);}}inline void tree_insert(int pre,int & now,int l,int r,int k){tr[now=++cntt].cnt=tr[pre].cnt+1;if(l==r) return;int mid=l+r>>1;if(k<=mid) {tr[now].r=tr[pre].r;tree_insert(tr[pre].l,tr[now].l,l,mid,k);}else {tr[now].l=tr[pre].l;tree_insert(tr[pre].r,tr[now].r,mid+1,r,k); }}inline void dfs1(int x,int fa)
        {son[x]++;tree_insert(root[fa],root[x],1,hash_tot,hash[x]);    for(int i=head[x];i;i=e[i].next){if(e[i].to==fa) continue;f[e[i].to]=x;dep[e[i].to]=dep[x]+1;dfs1(e[i].to,x);son[x]+=son[e[i].to];}}inline void dfs2(int x,int chain)//给重链编号
        {bl[x]=chain;int m=0;for(int i=head[x];i;i=e[i].next){if(e[i].to==f[x]) continue;if(son[e[i].to]>son[m]) m=e[i].to;}if(!m) return;dfs2(m,chain);for(int i=head[x];i;i=e[i].next){if(e[i].to==f[x]||e[i].to==m) continue;dfs2(e[i].to,e[i].to);} }inline int getlca(int u,int v)//求lca,本函数+上面2个函数为树链剖分求LCA
        {while(bl[u]!=bl[v]){if(dep[bl[u]]<dep[bl[v]]) swap(u,v);u=f[bl[u]];}if(dep[u]<dep[v]) return u;return v;}void discrete(){sort(a+1,a+n+1);hash_tot=unique(a+1,a+n+1)-(a+1);for(int i=1;i<=n;i++) hash[i]=lower_bound(a+1,a+hash_tot+1,hash[i])-a;}inline int tree_query(int x,int y,int lca,int fa_lca,int l,int r,int k){if(l==r) return a[l];int mid=l+r>>1,tmp=tr[tr[x].l].cnt+tr[tr[y].l].cnt-tr[tr[lca].l].cnt-tr[tr[fa_lca].l].cnt;if(k<=tmp) tree_query(tr[x].l,tr[y].l,tr[lca].l,tr[fa_lca].l,l,mid,k);else tree_query(tr[x].r,tr[y].r,tr[lca].r,tr[fa_lca].r,mid+1,r,k-tmp);}void init2(){int u,v,k;for(int i=1;i<=m;i++){u=read();v=read();k=read();u^=last;int lca=getlca(u,v);last=tree_query(root[u],root[v],root[lca],root[f[lca]],1,hash_tot,k);if(i!=m )printf("%d\n",last);else printf("%d",last);}}void work(){init();discrete();dfs1(1,0);dfs2(1,1);init2();}}a;
int main()
{a.work();
}

初做犯了一个很蠢的错误:最后一行不输出换行,楞是没看见

不读完题,第二次了。

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/6383854.html

Count on a tree相关推荐

  1. bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)

    Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB Submit: 7669  Solved: 1894 [Sub ...

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

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

  3. [SPOJ-COT]Count on a tree

    [SPOJ-COT]Count on a tree 题面 You are given a tree with N nodes. The tree nodes are numbered from 1 t ...

  4. BZOJ2588 Count on a tree 【树上主席树】

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB Submit: 7577  Solved: 185 ...

  5. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

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

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

  7. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  8. P2633 Count on a tree

    P2633 Count on a tree 题意: 给定一棵 n 个节点的树,每个点有一个权值.有 m 个询问,每次给你 u,v,k,你需要回答 u xor last 和 v 这两个节点间第 k 小的 ...

  9. SP10707 COT2 - Count on a tree II

    SP10707 COT2 - Count on a tree II 题意: 给定 n 个结点的树,每个结点有一种颜色. m 次询问,每次询问给出 u,v,回答 u,v 之间的路径上的结点的不同颜色数. ...

最新文章

  1. 测试方案_何小伟:ABTest测试方案
  2. (西瓜书)#版本空间与样本空间
  3. Nature调查 l 中国博士生们的科研围城
  4. 从零开始数据科学与机器学习算法-朴素贝叶斯-07
  5. TCP程序流程及服务器客户端
  6. ROS学习笔记1(配置ROS环境和创建工作空间)
  7. 【电子书】Head First Java
  8. 瓜瓜播放器android,瓜瓜视频播放器
  9. 智慧城管基础业务系统建设系统方案
  10. JAVA中小型医院信息管理系统源码 医院系统源码
  11. 决策树ID3算法实现与讨论(完整代码与数据)
  12. linux挂载移动硬盘 格式化_Linux下挂载移动硬盘(NTFS格式)
  13. V4L2视频采集的基本流程
  14. hbase scan超时设置_hbase scan limit 10
  15. python画简单的图形(结构,循环)
  16. 批处理登陆邮箱代码分析
  17. grep同时过滤多个条件
  18. html5核心ml5图片居中,HTML5图片居中的问题
  19. ellipsize实现跑马灯总结
  20. NERO刻录教程图解

热门文章

  1. 实验5_JPEG解码
  2. ROS Kinetic或ROS melodic下安装MoveIt!出现的问题:无法定位软件包 ros-kinetic-moveit-full或ros-melodic-moveit-full
  3. 【Tools】Modbus Poll 9安装详解
  4. 【Linux网络编程】网络字节序和地址转换
  5. 【Linux】一步一步学Linux——du命令(78)
  6. freetds php mssql 中文乱码,PHP读取mssql json数据中文乱码的解决办法
  7. 演讲者模式投影到幕布也看到备注_家用投影幕布怎么选?(看这一篇就明白了)...
  8. 在Linux虚拟机中添加多个ip地址
  9. 找到字符串中所有字母异位词—leetcode438
  10. Xcode 不用签名编译程序