传送门
写在前面:一天下来就写了两道主席树的题……(codevs上的一道智障天梯不算)
思路:
才知道原来主席树不仅可以通过dfs序维护子树区间,还可以直接维护一条到根的链……
我们建好主席树后,每次查询u->v路径上的第k大,无非有两种情况
1.u,v在同一条链上
2.u,v不在同一条链上
其实这两种情况处理起来是一样的,我们利用主席树中的前缀和思路,root[u]并上root[v]再减去root[lca(u,v)]再减去root[fa[lca(u,v)]]就是u->v路径上的点了(可以自己画图感受一下)
所以每次查询时要算四棵树之间的siz关系
注意:
1.求lca我用的是ST表,当然倍增也是可以的
2.最后一个答案不要换行!
代码:

#include<bits/stdc++.h>
#define M 100004
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
using namespace std;
int n,m,lastans,tot,maxn,cnt;
int fa[M],w[M],ID[M],first[M],dep[M],ST[M<<1][20],pos[M],num[M<<1];
struct disc
{int data,id;bool operator <(const disc other)const{return data<other.data;}
}d[M];
struct edge
{int u,v,next;
}e[M<<1];
struct Chairman_tree
{int siz,ch[2];
}a[M*20];
int in()
{char ch=getchar();int t=0;while (!isdigit(ch))ch=getchar();while (isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar();return t;
}
void add(int x,int y)
{e[++tot]=(edge){x,y,first[x]};first[x]=tot;e[++tot]=(edge){y,x,first[y]};first[y]=tot;
}
void build(int now,int L,int R,int rt,int val)
{a[rt].siz=a[now].siz+1;if (L==R) return;int mid=(L+R)>>1;if (mid>=val)rs(rt)=rs(now),ls(rt)=++cnt,build(ls(now),L,mid,ls(rt),val);elsea[rt].ch[0]=a[now].ch[0],a[rt].ch[1]=++cnt,build(rs(now),mid+1,R,rs(rt),val);
}
void dfs(int x)
{num[++num[0]]=x;pos[x]=num[0];ST[num[0]][0]=x;if (x==1) build(1,1,maxn,2,w[x]);for (int i=first[x];i;i=e[i].next)if (!pos[e[i].v]){dep[e[i].v]=dep[x]+1;fa[e[i].v]=x;build(x+1,1,maxn,e[i].v+1,w[e[i].v]);dfs(e[i].v);num[++num[0]]=x;ST[num[0]][0]=x;}
}
void init()
{int x,y;for (int i=1;i<=log2(num[0]);i++)for (int j=1;j<=num[0]-(1<<i)+1;j++)x=ST[j][i-1],y=ST[j+(1<<i-1)][i-1],ST[j][i]=(dep[x]>dep[y]?y:x);
}
int LCA(int x,int y)
{if (pos[x]>pos[y]) swap(x,y);int p=pos[x],q=pos[y],t=log2(q-p+1);if (dep[ST[p][t]]>dep[ST[q-(1<<t)+1][t]]) return ST[q-(1<<t)+1][t];else return ST[p][t];
}
int get(int begin,int end,int u,int v,int lca,int fa,int k)
{if (begin==end) return end;int mid=(begin+end)>>1;int t=a[ls(u)].siz+a[ls(v)].siz-a[ls(lca)].siz-a[ls(fa)].siz;if (k>t)return get(mid+1,end,rs(u),rs(v),rs(lca),rs(fa),k-t);elsereturn get(begin,mid,ls(u),ls(v),ls(lca),ls(fa),k);
}
main()
{n=in();m=in();for (int i=1;i<=n;i++)w[i]=in(),d[i].id=i,d[i].data=w[i];sort(d+1,d+n+1);maxn=1;ID[1]=d[1].data;w[d[1].id]=1;for (int i=2;i<=n;i++){if (d[i].data!=d[i-1].data) maxn++,ID[maxn]=d[i].data;w[d[i].id]=maxn;}for (int i=1;i<n;i++)add(in(),in());cnt=n+1;dfs(1);init();int x,y,z,k;while (m--){x=in()^lastans;y=in();k=in();z=LCA(x,y);lastans=ID[get(1,maxn,x+1,y+1,z+1,fa[z]+1,k)];printf("%d",lastans);if (m) putchar('\n');}
}

【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA相关推荐

  1. bzoj2588: Spoj 10628. Count on a tree 主席树

    在每一个点的父亲做主席树,每次访问时用两个点的和减去其LCA和LCA父亲的和即可. #include<bits/stdc++.h> using namespace std; inline ...

  2. SPOJ 10628 Count on a tree 主席树 附数据生成器

    很奇怪的题啊,感觉思路和别人一样,但是我得用快速IO才能AC--不然就T 没用快速output,只用了快速input 而且居然限制代码长度...代码要短于6000B,我改了好久啊 题目大意:给一棵树, ...

  3. SPOJ COT Count on a tree 主席树

    题意: 给\(n(1 \leq n \leq 10^5)\)一棵树,每个点有个权值. 还有\(m(1 \leq m \leq 10^5)\)个询问: \(u \, v \, k\),查询路径\(u \ ...

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

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

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

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

  6. HDU - 3804 Query on a tree(主席树维护最大值+离散化)

    题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...

  7. [bzoj2588] Count on a tree

    洛谷 P2633 传送门 bzoj 2588 传送门 一道树上差分的题. 每个点都建一个权值线段树,维护的是从这个点到根的链的信息. 这样就可以用主席树了,每个点的版本由其父节点的版本加上该点的权值得 ...

  8. ACM模板——线段树树状数组ST表

    int bit[maxn],n; void init() {n = maxn;memset(bit,0,sizeof(bit)); } int sum(int i) {int s = 0;while( ...

  9. POJ2823 Sliding Window【单调队列】【线段树】【ST表】

    Sliding Window POJ - 2823 题意: 给出一个长度为N的序列,通过一个窗口,可以看到序列中连续的K个元素,窗口从最左边出发,每次移动一个单位,对于每次移动,输出当前窗口中的最大值 ...

最新文章

  1. c语言折半查找法_C语言学习|选择法排序及折半查找法查找
  2. c语言派,C语言中 派/4=1-1/3+1/5-1/7....公式求派
  3. 新媒体技术发展迅猛 手机将让生活产生巨变(转)
  4. 一步一步教你使用AgileEAS.NET基础类库进行应用开发-WinForm应用篇-在UI中应用DataUIMapper组件...
  5. 程序员让开,硅谷将是物理学家的天下,薪水高得离谱
  6. HDU 4069 Squiggly Sudoku
  7. shell 布尔运算
  8. 4412的linux启动原理,友坚科技三星4412开发板Linux平台下UT4412BV03裸机开发指南(十一)...
  9. js控制的动画,显示隐藏(元素,动画,显示隐藏)
  10. 古风系统仙侠文推荐_5本古典仙侠全本精品小说,文笔精湛,仙味十足,值得细品一二...
  11. 实验1 Bean管理
  12. 华为AR路由器的无线AC和AP分别是指什么
  13. (几何方面:六边形面积)编写程序,提示用户输入六边形的边长,然后输出显示它的面积。 计算六边形面积的公式是:area= s2 这里的s就是边长。下面是一个运行示例: 请输入边长:5.5
  14. Python编程基础 第七章 编程练习 用户从键盘上输入一个字符串,如果该字符串的内容不是有效的数值,则输出invalid;如果是有效的数值,再判断其是否是整数,如果是整数则输出yes,否则输出no。
  15. 《 Python List列表全实例详解系列(五)》——修改元素(修改单个、修改一组)
  16. 树莓派PICO问题一
  17. 查违章老显示服务器维护中咋回事,违章查询怎么老显示系统正在维护呢,为什么违章查询总是显示维护状态?...
  18. 深度学习入门与快速实践
  19. linux服务器经常断网,linux-使用screen,防止断网导致异常退出
  20. 高通8155/8295 boot分析

热门文章

  1. 史上规模最大的中文知识图谱以及估值两个亿的 AI 核心代码
  2. 设计模式的C语言应用-非典型模式-第十章
  3. 用Python识别验证码
  4. Think in Java第四版 读书笔记9第15章 泛型
  5. Matlab中矩阵编号方式以及一维二维三维数据间的相互转换
  6. 虚拟机VMware下安装Linux系统,Python3.7之TensorFlow安装
  7. Java回文数.如12321,123454321(5个数)
  8. mysql建立外键快捷方式_mysql建立外键
  9. xml格式怎么转换excel_pdf怎么转换成excel?这个转换技巧你值得拥有!
  10. python 字典长度_python字典可以容纳多少个元素?