这是一道无比繁琐的题目
话说这道题使我第一次练dfs序,比较感动;
首先dfs序就是在dfs过程中按照访问的顺序给每个点标上两个“时间戳”
一个是第一次访问到点i时的时间戳c[i],一个是访问完以i为根时的时间戳cc[i]
根据c[i],我们就可以将树变成序列,并且以i为根的子树,是序列上连续的一段
当进行单点修改时,我们可以用树状数组前缀和维护树上的点到根路径上所有点的修改情况和;
比如当点i修改时(比如+1) 则w[c[i]]+1,w[cc[i]]-1
然后这道题显然是要在dfs序上套带修改的主席树,根据bzoj2588的经验我们很好解决这个问题
由于修改的点要离散化,已经离线了,干脆用lca-tarjan求lca好了
由于空间卡的比较严,所以我们不能直接树状数组+主席树
而要先把原树建成主席树,然后修改的时候新建一棵主席树,用树状数组+主席树解决
const maxn=; type node=record
po,next:longint;
end;
link=record
l,r,s:longint;
end;
point=record
x,y,z:longint;
end;
qu=record
num,loc,next:longint;
end; var tree:array[..] of link;
q:array[..] of point;
w:array[..] of node;
que:array[..] of qu;
v:array[..] of boolean;
e:array[..] of longint;
g,fa,an,loc,d1,d2,ph,h,cc,c,b:array[..] of longint;
st:array[..,..] of longint;
sa,a:array[..] of longint;
j,k,t,tot,num,len,x,y,z,i,p,s,n,m:longint; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; procedure update(x:longint);
begin
tree[x].s:=tree[tree[x].l].s+tree[tree[x].r].s;
end; procedure add(x,y:longint);
begin
inc(len);
w[len].po:=y;
w[len].next:=d1[x];
d1[x]:=len;
end; procedure addq(x,y,z:longint);
begin
inc(num);
que[num].num:=y;
que[num].loc:=z;
que[num].next:=d2[x];
d2[x]:=num;
end; function find(x:longint):longint;
var l,r,m:longint;
begin
l:=;
r:=p;
while l<=r do
begin
m:=(l+r) shr ;
if sa[m]=x then exit(m);
if sa[m]>x then r:=m- else l:=m+;
end;
end; function getf(x:longint):longint;
begin
if a[x]<>x then a[x]:=getf(a[x]);
exit(a[x]);
end; procedure dfs(x:longint);
var i,y:longint;
begin
i:=d1[x];
v[x]:=true;
inc(tot);
b[tot]:=x; //b表示序列上的点对应的树上的哪个点
c[x]:=tot;
while i<> do
begin
y:=w[i].po;
if not v[y] then
begin
fa[y]:=x;
dfs(y);
a[y]:=x;
end;
i:=w[i].next;
end;
cc[x]:=tot;
i:=d2[x];
while i<> do
begin
y:=que[i].num;
if v[y] and (an[que[i].loc]=) then //lca-tarjan
an[que[i].loc]:=getf(y);
i:=que[i].next;
end;
end; procedure sort(l,r: longint);
var i,j,x,y: 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
y:=a[i];
a[i]:=a[j];
a[j]:=y;
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 m,q: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 insert(last,x,l,r,z:longint):longint;
var m,q:longint;
begin
inc(t);
if l=r then
begin
tree[t].s:=tree[last].s+z;
exit(t);
end
else begin
m:=(l+r) shr ;
q:=t;
if x<=m then
begin
tree[q].r:=tree[last].r;
last:=tree[last].l;
tree[q].l:=insert(last,x,l,m,z);
end
else begin
tree[q].l:=tree[last].l;
last:=tree[last].r;
tree[q].r:=insert(last,x,m+,r,z);
end;
update(q);
exit(q);
end;
end; procedure work(i,x,z:longint);
begin
while i<=n do //树状数组+主席树
begin
h[i]:=insert(h[i],x,,p,z);
i:=i+lowbit(i);
end;
end; procedure get(x,y:longint);
var i:longint;
begin
e[y]:=;
st[,y]:=ph[x];
i:=x;
while i> do
begin
if h[i]<> then
begin
inc(e[y]);
st[e[y],y]:=h[i];
end;
i:=i-lowbit(i);
end;
end; function sum:longint;
var i,j:longint;
begin
sum:=;
for j:= to do
for i:= to e[j] do
if (j<=) then
sum:=sum+tree[tree[st[i,j]].r].s
else sum:=sum-tree[tree[st[i,j]].r].s;//u,v路径上的情况为tree[u]+tree[v]-tree[lca(u,v)]-tree[fa[lca(u,v)]];
end; function getans(l,r,k:longint):longint;
var m,s,i,j:longint;
begin
if l=r then exit(sa[l])
else begin
m:=(l+r) shr ;
s:=sum;
if s>=k then
begin
for j:= to do
for i:= to e[j] do
st[i,j]:=tree[st[i,j]].r;
exit(getans(m+,r,k));
end
else begin
k:=k-s;
for j:= to do
for i:= to e[j] do
st[i,j]:=tree[st[i,j]].l;
exit(getans(l,m,k));
end;
end;
end; begin
readln(n,m);
for i:= to n do
begin
read(g[i]);
a[i]:=g[i];
end;
s:=n;
for i:= to n- do
begin
readln(x,y);
add(x,y);
add(y,x);
end; for i:= to m do
begin
readln(q[i].z,q[i].x,q[i].y);
if q[i].z= then
begin
inc(s);
a[s]:=q[i].y;
end
else begin
addq(q[i].x,q[i].y,i);
addq(q[i].y,q[i].x,i);
end;
end;
sort(,s);
p:=;
sa[]:=a[];
for i:= to s do
if a[i]<>a[i-] then //离散化
begin
inc(p);
sa[p]:=a[i];
end; for i:= to n do
a[i]:=i;
dfs();
t:=;
h[]:=build(,p);
ph[]:=h[];
for i:= to n do
begin
loc[i]:=find(g[b[i]]);
y:=fa[b[i]];
ph[i]:=insert(ph[c[y]],loc[i],,p,); //建立未修改前的主席树
end;
for i:= to m do
begin
if q[i].z<> then
begin
z:=an[i];
get(c[q[i].x],); //提取区间
get(c[q[i].y],);
get(c[z],);
get(c[fa[z]],);
s:=;
for j:= to do
begin
for k:= to e[j] do
if (j<=) then
s:=s+tree[st[k,j]].s
else s:=s-tree[st[k,j]].s;
end;
if s<q[i].z then writeln('invalid request!')
else writeln(getans(,p,q[i].z));
end
else begin
x:=q[i].x;
work(c[x],loc[c[x]],-);
work(cc[x]+,loc[c[x]],);
loc[c[x]]:=find(q[i].y);
work(c[x],loc[c[x]],);
work(cc[x]+,loc[c[x]],-);
end;
end;
end.
bzoj1146的更多相关文章
-
[BZOJ1146][CTSC2008]网络管理Network
[BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...
-
【BZOJ1146】网络管理(整体二分)
[BZOJ1146]网络管理(整体二分) 题面 良心洛谷,有BZOJ权限题 题解 要看树套树的戳这里 毕竟是:智商不够数据结构来补 所以, 我们来当一回智商够的选手 听说主席树的题目大部分都可以整体二 ...
-
【BZOJ1146】网络管理(主席树,树状数组)
[BZOJ1146]网络管理(主席树,树状数组) 题面 BZOJ权限题,洛谷题面 题解 树上带修改主席树 貌似和\(Count\ On\ A\ Tree\)那题很相似呀 只需要套上一个树状数组来维护修 ...
-
BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...
-
[BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
-
【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
-
【BZOJ-1146】网络管理Network DFS序 + 带修主席树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3495 Solved: 1032[Submi ...
-
BZOJ1146——[CTSC2008]网络管理Network
1.题目大意:就是在动态的树上路径权值第k大. 2.分析:这个就是树链剖分+树套树 #include <cstdio> #include <cstdlib> #include ...
-
bzoj1146整体二分+树链剖分+树状数组
其实也没啥好说的 用树状数组可以O(logn)的查询 套一层整体二分就可以做到O(nlngn) 最后用树链剖分让序列上树 #include<cstdio> #include<cstr ...
-
【BZOJ1146】【树链剖分+平衡树】网络管理Network
Description M 公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 信网络.该网络的结构由N个 ...
随机推荐
-
在Ubuntu上安装网易云音乐
对于网易,我只服云音乐,业界良心,用过的人都知道.我最喜欢的就是歌曲的评论功能,还有朋友圈子.里面有很多好段子,还有很多的好故事,基本上,不是分手,就是回忆初恋,还有吐槽的.我认为音乐带给人的不仅是耳 ...
-
javascript日历控件——纯javascript版
平时只有下班时间能code,闲来写了个纯javascript版.引用该calendar.js文件,然后给要设置成日历控件的input的id设置成calendar,该input就会变成日历控件. < ...
-
第一百零五节,JavaScript正则表达式
JavaScript正则表达式 学习要点: 1.什么是正则表达式 2.创建正则表达式 3.获取控制 4.常用的正则 假设用户需要在HTML表单中填写姓名.地址.出生日期等.那么在将表单提交到服务器进一 ...
-
Ubuntu 14.04下Redis安装报错:“You need tcl 8.5 or newer in order to run the Redis test”问题解决
Redis简介: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工 ...
-
ajaxfileupload原理及用法,主要用于即想用ajax序列化传递参数,又必须上传文件
一,原理 AjaxFileUpload.js并不是一个很出名的插件,只是别人写好的放出来供大家用,原理都是创建隐藏的表单和iframe然后用JS去提交,获得返回值. 当初做了个异步上传的功能,选择它因 ...
-
ThinkPHP 数据库操作(三) : 查询方法、查询语法、链式操作
查询方法 条件查询方法 where 方法 可以使用 where 方法进行 AND 条件查询: Db::table('think_user') ->where('name','like','%th ...
-
第十四章 Java常用类
14.常用类 14.1 字符串相关的类 1课时 14.2 JDK 8之前时间日期API 1课时 14.3 JDK8中新时间日期API 1课时 14.4 JDK8中的Optional类 1课时 14.5 ...
-
深入出不来nodejs源码-timer模块(JS篇)
鸽了好久,最近沉迷游戏,继续写点什么吧,也不知道有没有人看. 其实这个node的源码也不知道该怎么写了,很多模块涉及的东西比较深,JS和C++两头看,中间被工作耽搁回来就一脸懵逼了,所以还是挑一些简单 ...
-
linux soname
在linux下使用动态库时,经常会发现明明编译时指定的是libA.so,可是程序运行时或通过ldd查看依赖却是libA.so.XXX, 原因跟linux下so库的soname有关,查看so库的sona ...
-
JVM监控常用命令行工具
jps jps -mlv //列出正在运行的虚拟机进程 jstat jstat -gc pid //监视java堆状况 显示列名 具体描述 S0C 年轻代中第一个survivor(幸存区)的容量 (字 ...