bzoj 2588 Count on a tree
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
树上的主席树,本来应该自已YY一下的但是没有想出来。。。尴尬。。。
其实还是很简单的。。。
每个节点以其父亲节点为历史版本建主席树,在dfs的时候insert;
那么每个点的线段树相当于是维护了从根节点到该节点路径上的点。。。
对于树上两点l,r路径上的第k大,那么要找出l,r的LCA,由于这个LCA也是需要被考虑的,所以还要求LCA的爸爸;
所以每次相当于是 s[ls[l]]+s[ls[r]]-s[ls[lca]]-s[ls[fa[lca]];
这个东西把图画出来,其实就是一个树上的前缀和思想。。。
附上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int gi()
{
int x=,flag=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') flag=-;ch=getchar();}
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x*flag;
}
int hash[N],num[N],v[N],s[N*],sz,root[N],ls[N*],rs[N*];
int dfn[N],head[N*],nxt[N*],to[N*],son[N],dep[N],size[N],fa[N],top[N];
int id[N],tt,cnt,tot,n,m,last;
int find(int x)
{
int l=,r=tot;
while(l<=r)
{
int mid=(l+r)>>;
if(hash[mid]<x) l=mid+;
else r=mid-;
}
return l;
}
void insert(int l,int r,int x,int &y,int k)
{
y=++sz;
s[y]=s[x]+;ls[y]=ls[x],rs[y]=rs[x];
if(l==r) return;
int mid=(l+r)>>;
if(k<=mid) insert(l,mid,ls[x],ls[y],k);
else insert(mid+,r,rs[x],rs[y],k);
}
int query(int l,int r,int a,int b,int c,int d,int k)
{
if(l==r) return hash[l];
int mid=(l+r)>>;
if(s[ls[a]]+s[ls[b]]-s[ls[c]]-s[ls[d]]>=k)
return query(l,mid,ls[a],ls[b],ls[c],ls[d],k);
else return query(mid+,r,rs[a],rs[b],rs[c],rs[d],k-(s[ls[a]]+s[ls[b]]-s[ls[c]]-s[ls[d]]));
}
void dfs1(int x,int f)
{
dep[x]=dep[f]+;size[x]=;
insert(,tot,root[f],root[x],find(v[x]));
for(int i=head[x]; i; i=nxt[i])
{
int y=to[i];
if(y!=f)
{
dfs1(y,x);
fa[y]=x;size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
}
void dfs2(int x,int f)
{
dfn[x]=++tt,top[x]=f;
if(son[x]) dfs2(son[x],f);
for(int i=head[x]; i; i=nxt[i])
{
int y=to[i];
if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
return y;
}
void lnk(int x,int y)
{
to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
}
int main()
{
n=gi(),m=gi();
for(int i=; i<=n; i++) v[i]=gi(),num[i]=v[i];
sort(num+,num++n);
hash[++tot]=num[];
for(int i=; i<=n; i++)
if(num[i]!=num[i-])
hash[++tot]=num[i];
int x,y,k;
for(int i=; i<n; i++) x=gi(),y=gi(),lnk(x,y);
dfs1(,);dfs2(,);
for(int i=; i<=m; i++)
{
x=gi();y=gi();k=gi();x^=last;
int a=root[x],b=root[y],c=root[lca(x,y)],d=root[fa[lca(x,y)]];
last=query(,tot,a,b,c,d,k);
printf("%d",last);if(i!=m) printf("\n");
}
}
bzoj 2588 Count on a tree的更多相关文章
- bzoj 2588 Count on a tree 解题报告
Count on a tree 题目描述 给定一棵\(N\)个节点的树,每个点有一个权值,对于\(M\)个询问\((u,v,k)\),你需要回答\(u\) \(xor\) \(lastans\)和\( ...
- BZOJ 2588 Count on a tree (COT) 是持久的段树
标题效果:两棵树之间的首次查询k大点的权利. 思维:树木覆盖树,事实上,它是正常的树木覆盖了持久段树. 由于使用权值段树可以寻求区间k大,然后应用到持久段树思想,间隔可以做减法.详见代码. CODE: ...
- BZOJ.2588.Count on a tree(主席树 静态树上第k小)
题目链接 /* 序列上的主席树 某点是利用前一个点的根建树 同理 树上的主席树 某个节点可以利用其父节点(is unique)的根建树 排名可以利用树上前缀和求得: 对于(u,v),w=LCA(u,v ...
- 2588: Count on a tree
敢问和zwt的树有何区别..改了读入直接交..四百个人A,三百多个PE..于是果断贡献几发PE.. http://ideone.com/9XCg3D
- 【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: 12 Sec Memory Limit: 128 MBSubmit: 5217 Solved: 1233 ...
- 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 ...
- 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的这条路径上的权值线段树 ----------------------- ...
随机推荐
- 快速排序Golang版本
Created by jinhan on --. Tip: http://blog.csdn.net/zhengqijun_/article/details/53038831 See: https:/ ...
- web离线应用 Web SQL Database
web sql database 是html5废弃的一个新特性,它提供了基本的关系数据库功能,使用 `SQL` 来操纵客户端数据库的 API,这些 API 是异步的,规范中使用的方言是SQLlite ...
- Centos 安装boost库
1.在http://www.boost.org/下载boost安装包boost_1_65_1.tar.gz 2.在Centos上解压tar -zxvf boost_1_65_1.tar.gz后,cd ...
- C#爬虫系列(一)——国家标准全文公开系统
网上有很多Python爬虫的帖子,不排除很多培训班借着AI的概念教Python,然后爬网页自然是其中的一个大章节,毕竟做算法分析没有大量的数据怎么成. C#相比Python可能笨重了些,但实现简单爬虫 ...
- Akka(42): Http:身份验证 - authentication, autorization and use of raw headers
当我们把Akka-http作为数据库数据交换工具时,数据是以Source[ROW,_]形式存放在Entity里的.很多时候除数据之外我们可能需要进行一些附加的信息传递如对数据的具体处理方式等.我们可以 ...
- jQuer __Ajax DOM
链接:在线jQueryhttp://www.bootcdn.cn 一.each(遍历) $("ul li").each(function(index,value){ ale ...
- DOMContentLoaded、readystatechange、load、ready详谈
对前端同学而言,loade,unload,DOMContentLoaded等页面加载过程中会触发的事件肯定是都接触过,不过要是具体问各个事件的区别,我就不是那么能清晰的解答上来的了.正好刚刚在无阻塞脚 ...
- 关于我之前写的修改Windows系统Dos下显示用用户名的名字再测试
最近看到蛮多网友反映,自己修改Dos下用户名后出现了很多的问题--今天抽了时间,再次修改测试... ================= Win10下C:\Users\John以账户名称命名的系统文件夹 ...
- Python爬虫(九)_非结构化数据与结构化数据
爬虫的一个重要步骤就是页面解析与数据提取.更多内容请参考:Python学习指南 页面解析与数据提取 实际上爬虫一共就四个主要步骤: 定(要知道你准备在哪个范围或者网站去搜索) 爬(将所有的网站的内容全 ...
- JSON数据解析及gson.jar包
从服务器端接收数据的时候,那些数据必须以浏览器能够理解的格式来发送. 服务器端的编程语言只能以如下 3 种格式返回数据: HTML XML JSON JSON一种简单的数据格式,比xml更轻巧. JS ...