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的这条路径上的权值线段树 ----------------------- ...
随机推荐
- Python开发目录
Python开发目录 Python之三目运算符 Python之文件的基本操作
- Mybatis分页插件PageHelper简单使用
一个好的讲解mybatis的博客地址http://www.jianshu.com/nb/5226994 引言 对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句 ...
- webpack构建项目
webpack构建项目 案例代码戳这里 ps:每个案例对应相应的demo,例如"案例1"对应"demo1" 一.webpack基本功能及简单案例 安装webpa ...
- 【NOIP2015提高组】跳石头
https://www.luogu.org/problem/show?pid=2678 最小值最大问题,二分答案.每次检查是否能仅移走m块岩石使得所有跳跃距离均大于等于mid. #include &l ...
- day1-Python入门
百度云有关文档资料链接 链接:https://pan.baidu.com/s/1pLighnX 密码:j69s
- 采用Opserver来监控你的ASP.NET项目系列(二、监控SQL Server与Asp.Net项目)
前言 之前有过2篇关于如何监控ASP.NET core项目的文章,有兴趣的也可以看看. 今天我们主要来介绍一下,如何使用Opserver监控我们的SQL Server 和ASP.NET项目的异常监控 ...
- 网络相关系列之三:通过GET和POST方法发送数据
写在最前面:年少的安逸舒适在随着年龄的到来和现实生活的压迫总有一天会全数归还(事实上就是<无间道>中那句:"出来混,迟早要还的!") so fighting. 一.GE ...
- c语言中字符串函数的使用
#include<stdio.h> #include<string.h> /* char s1[]="I am a student"; char s2[20 ...
- 基于Handler架构的录音程序
近期我的app须要一个录音功能,于是搜到这篇文章 文章中录音线程与主线程间的通讯是通过内部类訪问外部类成员变量的方式来实现 while (isRecord == true) { //isRecord是 ...
- Android View视图系统分析和Scroller和OverScroller分析
Android View视图系统分析和Scroller和OverScroller分析 View 视图分析 首先,我们知道.在Android中全部的视图资源(无论是Layout还是V ...