Count on a tree
bzoj 2588: Spoj 10628. Count on a tree
http://www.lydsy.com/JudgeOnline/problem.php?id=2588
Description
Input
Output
M行,表示每个询问的答案。最后一个询问不输出换行符
Sample Input
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
8
9
105
7
HINT
Source
数据结构:主席树
辅助算法: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*];
- struct data {int to,next;}e[N*];
- 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=,f=;char c=getchar();
- while(c<''||c>'') {if(c=='-') f=-;c=getchar();}
- while(c>=''&&c<='') {x=x*+c-'';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=;i<=n;i++) a[i]=read(),hash[i]=a[i];
- int u,v;
- for(int i=;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+;
- if(l==r) return;
- int mid=l+r>>;
- 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+,r,k);
- }
- }
- inline void dfs1(int x,int fa)
- {
- son[x]++;
- tree_insert(root[fa],root[x],,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]+;
- dfs1(e[i].to,x);
- son[x]+=son[e[i].to];
- }
- }
- inline void dfs2(int x,int chain)//给重链编号
- {
- bl[x]=chain;
- int m=;
- 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+,a+n+);
- hash_tot=unique(a+,a+n+)-(a+);
- for(int i=;i<=n;i++) hash[i]=lower_bound(a+,a+hash_tot+,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>>,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+,r,k-tmp);
- }
- void init2()
- {
- int u,v,k;
- for(int i=;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]],,hash_tot,k);
- if(i!=m )printf("%d\n",last);
- else printf("%d",last);
- }
- }
- void work()
- {
- init();
- discrete();
- dfs1(,);
- dfs2(,);
- init2();
- }
- }a;
- int main()
- {
- a.work();
- }
初做犯了一个很蠢的错误:最后一行不输出换行,楞是没看见
不读完题,第二次了。
Count on a tree的更多相关文章
- 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 ...
- SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
- 【BZOJ-2588】Count on a tree 主席树 + 倍增
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 3749 Solved: 873[ ...
- 【BZOJ】【2588】COT(Count On a Tree)
可持久化线段树 maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树. 然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 19 ...
- 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 ...
- spoj cot: Count on a tree 主席树
10628. Count on a tree Problem code: COT You are given a tree with N nodes.The tree nodes are number ...
- 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 ...
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...
- SPOJ Count on a tree
Count on a tree Time Limit:129MS Memory Limit:1572864KB 64bit IO Format:%lld & %llu Subm ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
随机推荐
- 【BZOJ4071】八邻旁之桥(线段树)
[BZOJ4071]八邻旁之桥(线段树) 题面 BZOJ权限题,洛谷链接 题解 既然\(k<=2\) 那么,突破口就在这里 分类讨论 ①\(k=1\) 这...不就是中位数吗.... 直接把所有 ...
- Luogu3613 睡觉困难综合征
题面描述https://www.luogu.org/problemnew/show/3613 原题NOI2014起床困难综合症https://www.luogu.org/problemnew/show ...
- LightOJ1259 Goldbach`s Conjecture
题面 T组询问,每组询问是一个偶数n 验证哥德巴赫猜想 回答n=a+b 且a,b(a<=b)是质数的方案个数 Input Input starts with an integer T (≤ 30 ...
- app图标icon大全
http://tool.58pic.com/tubiaobao/index.php?m=Index&a=ui&p=2 很有用,下载没用,直接右键吧.
- gulp+babel面向未来变成
1.需要本地安装node; 2.安装gulp: 3.在项目根目录启动node; 安装babel组件: npm install --save-dev babel-core npm install --s ...
- Spring Boot 系列(八)@ControllerAdvice 拦截异常并统一处理
在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有@Requ ...
- 关于 promise 吃到错误的理解
关于 promise 吃到错误的理解 下面的内容需要对浏览器原生支持的 promise 的基本用法有了解,如果你还不知道 promise 和 promise 的 catch 方法,你可能需要先在 这里 ...
- selenium 学习之路开始了,一遍搬一遍理解学习,加油!!!
selenium 学习之路开始了,一遍搬一遍理解学习,加油!!!
- spring Boot+spring Cloud实现微服务详细教程第一篇
前些天项目组的大佬跟我聊,说项目组想从之前的架构上剥离出来公用的模块做微服务的开发,恰好去年的5/6月份在上家公司学习了国内开源的dubbo+zookeeper实现的微服务的架构.自己平时对微服务的设 ...
- getPropertyValue 获取CSS样式
新学习一个js 的方法 getPropertyValue (实现 js框架中 css 的最终调用的函数),取得元素最终计算出的css 样式 DEMO: <!DOCTYPE html> ...