bzoj2588
一开始一看树上的操作,就无脑写了树链剖分+主席树
然后果断T了,因为树链剖分+主席树必然带来两个log的复杂度
而且树链剖分复杂度还比较大……
后来发现其实没必要,在这道题,我们可以直接利用主席树维护
只不过,每个点维护的是它到它的祖先上数值出现的个数
则u,v之间各个数值出现的数值=tree[u]+tree[v]-tree[lca(u,v)]-tree[fa[lca(u,v)]];
这是一个满足区间减法的问题所以可以这么做
总结一下,在静态树上(相对于动态树而言,没有改变树的形态)
如果问题满足区间减法性质,如求k大,那就直接做,或者用dfs序(下篇再写)
如果不满足,那就要套树链剖分了
const maxn=;
type node=record
po,next:longint;
end;
point=record
l,r,s:longint;
end; var tree:array[..maxn*] of point;
w:array[..*maxn] of node;
h,p,c,b,a,q1,q2,rank,sa,fa,d:array[..maxn] of longint;
anc:array[..maxn,..] of longint;
j,t,z,e,i,n,m,k,x,y,len,ans,s:longint; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure update(i:longint);
begin
tree[i].s:=tree[tree[i].l].s+tree[tree[i].r].s;
end; procedure add(x,y:longint);
begin
inc(len);
w[len].po:=y;
w[len].next:=p[x];
p[x]:=len;
end; procedure sort(l,r: longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) div ];
repeat
while (a[i]<x) do inc(i);
while (x<a[j]) do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
swap(c[i],c[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; function build(l,r:longint):longint;
var q,m:longint;
begin
inc(t);
if l=r then exit(t)
else begin
q:=t;
m:=(l+r) shr ;
tree[q].l:=build(l,m);
tree[q].r:=build(m+,r);
exit(q);
end;
end; function add(last,l,r,x:longint):longint;
var q,m:longint;
begin
inc(t);
if l=r then
begin
tree[t].s:=tree[last].s+;
exit(t);
end
else begin
q:=t;
m:=(l+r) shr ;
if x<=m then
begin
tree[q].r:=tree[last].r;
last:=tree[last].l;
tree[q].l:=add(last,l,m,x);
end
else begin
tree[q].l:=tree[last].l;
last:=tree[last].r;
tree[q].r:=add(last,m+,r,x);
end;
update(q);
exit(q);
end;
end; function getans(l,r,k:longint):longint;
var i,m,s1:longint;
begin
if l=r then
exit(sa[l])
else begin
m:=(l+r) shr ;
s1:=tree[tree[x].l].s+tree[tree[y].l].s-tree[tree[z].l].s-tree[tree[e].l].s;
if s1>=k then
begin
x:=tree[x].l;
y:=tree[y].l;
z:=tree[z].l;
e:=tree[e].l;
exit(getans(l,m,k));
end
else begin
x:=tree[x].r;
y:=tree[y].r;
z:=tree[z].r;
e:=tree[e].r;
k:=k-s1;
exit(getans(m+,r,k));
end;
end;
end; function lca(x,y:longint):longint;
var i,p:longint;
begin
if d[x]<d[y] then swap(x,y);
if x=y then exit(x);
p:=trunc(ln(d[x])/ln());
for i:=p downto do
if d[x]- shl i>=d[y] then x:=anc[x,i];
if x=y then exit(x);
for i:=p downto do
if (anc[x,i]<>anc[y,i]) and (anc[x,i]<>) then
begin
x:=anc[x,i];
y:=anc[y,i];
end;
exit(fa[x]);
end; procedure dfs(x:longint);
var i,y:longint;
begin
h[x]:=add(h[fa[x]],,s,rank[x]);
i:=p[x];
while i<> do
begin
y:=w[i].po;
if fa[x]<>y then
begin
d[y]:=d[x]+;
fa[y]:=x;
dfs(y);
end;
i:=w[i].next;
end;
end; begin
readln(n,m);
for i:= to n do
begin
read(a[i]);
c[i]:=i;
end;
sort(,n);
s:=;
sa[]:=a[];
rank[c[]]:=;
for i:= to n do
begin
if a[i]<>a[i-] then
begin
inc(s);
sa[s]:=a[i];
end;
rank[c[i]]:=s;
end;
for i:= to n- do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
h[]:=build(,s);
dfs(); for i:= to n do
anc[i,]:=fa[i];
k:=trunc(ln(n)/ln());
for j:= to k do
for i:= to n do
begin
x:=anc[i,j-];
if x<> then anc[i,j]:=anc[x,j-];
end; ans:=;
for i:= to m do
begin
readln(x,y,k);
x:=x xor ans;
z:=lca(x,y);
e:=h[fa[z]];
z:=h[z];
x:=h[x];
y:=h[y];
ans:=getans(,s,k);
write(ans);
if i<>m then writeln;
end;
end.
bzoj2588的更多相关文章
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA
[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...
- 【bzoj2588】Count on a tree
Portal -->bzoj2588 Solution 不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢..) 额首先说一下正解 如果这个问题放在序列上面的话..直接离散化一下然后 ...
- 洛谷P2633/bzoj2588 Count on a tree (主席树)
洛谷P2633/bzoj2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K ...
- BZOJ2588 SPOJ10628 Count on a tree 【主席树】
BZOJ2588 Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中l ...
- [bzoj2588][Spoj10628]Count on a tree_主席树
Count on a tree bzoj-2588 Spoj-10628 题目大意:给定一棵n个点的树,m次查询.查询路径上k小值. 注释:$1\le n,m\le 10^5$. 想法:好像更博顺序有 ...
- [bzoj2588][count on a tree] (主席树+lca)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- BZOJ2588: Spoj 10628. Count on a tree
传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...
- 【填坑向】spoj COT/bzoj2588 Count on a tree
这题是学主席树的时候就想写的,,, 但是当时没写(懒) 现在来填坑 = =日常调半天lca(考虑以后背板) 主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分 ...
- bzoj2588 Count on a tree
题意:给定一棵树,有点权,不带修改,询问路径点权第K大,强制在线. 这道题建主席树的方法好机智.按照BFS/DFS序建树,对于每个点,建出"这个点到根节点的路径上的点"组成的权值线 ...
随机推荐
- JS 模拟C# 字符串格式化操作
/*** ** 功能: 字符串格式化替换操作 ***/ String.prototype.format = function () { var args = arguments; return thi ...
- C++ hello world
日文版本的vs 2008 , 在 < 新建 里面先创建一个项目 然后点击项目去创建一个C++的主启动文件 选择创建的文件类型 然后在文件里面写入代码 #include<iostream&g ...
- python爬虫scrapy的Selectors参考文档
http://doc.scrapy.org/en/1.0/topics/selectors.html#topics-selectors-htmlcode
- 自定义Window 服务
自定义window 服务 开发到使用的流程: 1.完成对应的代码之后(代码在底下),右键MyService.cs 添加安装程序 2.添加window服务安装程序打开Service1.cs[设计]页面, ...
- Premature optimization is the root of all evil.
For all of we programmers,we should always remember that "Premature optimization is the root of ...
- CentOS7下安装SVN服务端
CentOS7下安装SVN服务 1. yum命令即可方便的完成安装# sudo yum install subversion 测试安装是否成功:# svnserve --version 更改svn的默 ...
- 在模型中获取网络数据,刷新tableView
model .h #import <Foundation/Foundation.h> #import "AFHTTPRequestOperationManager.h" ...
- 1、大部分社交平台接口不支持https协议。
参考文献来自:http://wiki.mob.com/ios9-%E5%AF%B9sharesdk%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%88%E9%80%82%E9%85 ...
- hbase的存储体系
一.了解hbase的存储体系. hbase的存储体系核心的有Split机制,Flush机制和Compact机制. 1.split机制 每一个hbase的table表在刚刚开始的时候,只有一个regio ...
- 2016.7.13abstract
abstract的使用: 1.当许多类中有相同的功能,功能的内容不同,那么我们向上提取功能的定义. 2当功能的定义被 abstract修饰后,那么它的类也要被abstract修饰,使其抽象化. 3被a ...