[BZOJ1984]月下“毛景树”解题报告|树链剖分
Description
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
program bzoj1984;
const maxn=;maxm=;
var n,i,j,x,y,z,cnt,t:longint;
ch:char;
ter,next,w:array[-..maxm]of longint;
link,deep,size,v,son,pos,belong:array[-..maxn]of longint;
tr:array[-..*maxn]of record l,r,mx,add,c:longint;wait:boolean;end;
fa:array[-..maxn,-..]of longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
end; procedure dfs1(p:longint);
var i,j:longint;
begin
size[p]:=;
for i:= to do
begin
if deep[p]<= << i then break;
fa[p][i]:=fa[fa[p][i-]][i-];
end;
j:=link[p];
while j<> do
begin
if deep[ter[j]]= then
begin
deep[ter[j]]:=deep[p]+;
fa[ter[j]][]:=p;
v[ter[j]]:=w[j];son[(j+) >> ]:=ter[j];
dfs1(ter[j]);
inc(size[p],size[ter[j]]);
end;
j:=next[j];
end;
end; procedure dfs2(p,chain:longint);
var j,k:longint;
begin
inc(cnt);pos[p]:=cnt;belong[p]:=chain;
k:=;
j:=link[p];
while j<> do
begin
if deep[ter[j]]>deep[p] then
if size[ter[j]]>size[k] then k:=ter[j];
j:=next[j];
end;
if k= then exit;
dfs2(k,chain);
j:=link[p];
while j<> do
begin
if deep[ter[j]]>deep[p] then
if k<>ter[j] then dfs2(ter[j],ter[j]);
j:=next[j];
end;
end; procedure build(p,l,r:longint);
var mid:longint;
begin
tr[p].l:=l;tr[p].r:=r;tr[p].mx:=;tr[p].wait:=false;tr[p].add:=;
if l=r then exit;
mid:=(l+r) >> ;
build(p << ,l,mid);
build(p << +,mid+,r);
end; procedure push(p:longint);
begin
if tr[p].l=tr[p].r then exit;
if tr[p].wait then
begin
//与上一题不同,这一题并不存在下面的点在更新之后能比现在更好的情况所以不需要push(p << 1);push(p << 1+1)
//否则会TLE
tr[p << ].add:=;tr[p << +].add:=;
//这两句很关键 因为当儿子节点再往下更新的时候如果add没有清零再往下的点会被赋上不等于tr[p].mx的值
tr[p << ].mx:=tr[p].mx;tr[p << ].wait:=true;
tr[p << +].mx:=tr[p].mx;tr[p << +].wait:=true;
tr[p].wait:=false;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
end;
if tr[p].add<> then
begin
inc(tr[p << ].mx,tr[p].add);
if not tr[p << ].wait then inc(tr[p << ].add,tr[p].add);
//这个特判很关键也很隐蔽 因为如果tr[p << 1].wait=True的话它往下传的时候应该把tr[p << 1].mx+tr[p].add传递下去
//但是如果把tr[p << 1].add也加上了tr[p].add的话相当于重复相加 就出错了
inc(tr[p << +].mx,tr[p].add);
if not tr[p << +].wait then inc(tr[p << +].add,tr[p].add);
tr[p].add:=;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
end;
end; procedure insert(p,l,r,ave:longint);
var mid:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
tr[p].mx:=ave;tr[p].wait:=true;
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then insert(p << ,l,r,ave) else
if l>mid then insert(p << +,l,r,ave) else
begin
insert(p << ,l,mid,ave);
insert(p << +,mid+,r,ave);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
end; function lca(x,y:longint):longint;
var tem,i:longint;
begin
if deep[x]<deep[y] then
begin
tem:=x;x:=y;y:=tem;
end;
if deep[x]<>deep[y] then
begin
i:=trunc(ln(deep[x]-deep[y])/ln());
while deep[x]>deep[y] do
begin
while (deep[x]-deep[y]>= << i) do x:=fa[x][i];
dec(i);
end;
end;
if x=y then exit(x);
i:=trunc(ln(n)/ln());
while fa[x][]<>fa[y,] do
begin
while fa[x,i]<>fa[y,i] do
begin
x:=fa[x,i];y:=fa[y,i];
end;
dec(i);
end;
exit(fa[x,]);
end; procedure add(p,l,r,ave:longint);
var mid:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
inc(tr[p].mx,ave);
inc(tr[p].add,ave);
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then add(p << ,l,r,ave) else
if l>mid then add(p << +,l,r,ave) else
begin
add(p << ,l,mid,ave);
add(p << +,mid+,r,ave);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
end; function query(p,l,r:longint):longint;
var mid:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then exit(query(p << ,l,r)) else
if l>mid then exit(query(p << +,l,r)) else
exit(max(query(p << ,l,mid),query(p << +,mid+,r)));
end; procedure solve_change(x,y,z:longint);
begin
while belong[x]<>belong[y] do
begin
insert(,pos[belong[x]],pos[x],z);
x:=fa[belong[x]][];
end;
if x<>y then insert(,pos[y]+,pos[x],z);
end; procedure solve_add(x,y,z:longint);
begin
while belong[x]<>belong[y] do
begin
add(,pos[belong[x]],pos[x],z);
x:=fa[belong[x]][];
end;
if x<>y then add(,pos[y]+,pos[x],z);
end; function solve_mx(x,y:longint):longint;
var sum:longint;
begin
sum:=;
while belong[x]<>belong[y] do
begin
sum:=max(sum,query(,pos[belong[x]],pos[x]));
x:=fa[belong[x]][];
end;
if x<>y then sum:=max(sum,query(,pos[y]+,pos[x]));
exit(sum);
end; begin
readln(n);
j:=;
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
end;
deep[]:=;dfs1();
cnt:=;dfs2(,);
build(,,n);
for i:= to n do insert(,pos[i],pos[i],v[i]);
read(ch);
while ch<>'S' do
begin
if ch='C' then
begin
read(ch);
if ch='h' then
begin
readln(ch,ch,ch,ch,x,y);
insert(,pos[son[x]],pos[son[x]],y);
end else
begin
readln(ch,ch,ch,x,y,z);
t:=lca(x,y);
solve_change(x,t,z);solve_change(y,t,z);
end;
end else
if ch='A' then
begin
readln(ch,ch,x,y,z);
t:=lca(x,y);
solve_add(x,t,z);solve_add(y,t,z);
end else
begin
readln(ch,ch,x,y);
t:=lca(x,y);
writeln(max(solve_mx(x,t),solve_mx(y,t)));
end;
read(ch);
end;
end.
[BZOJ1984]月下“毛景树”解题报告|树链剖分的更多相关文章
- BZOJ1984: 月下“毛景树”
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 713 Solved: 245[Submit][Status] Descri ...
- [bzoj1984]月下“毛景树”
Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园.毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的" ...
- 【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca. #include<cstdio> #include<cmath> ...
- 2018.10.27 bzoj1984: 月下“毛景树”(树链剖分)
传送门 唉蒟蒻又退化了,这道sb题居然做了20min,最后发现是updcovupdcovupdcov写成了updaddupdaddupdadd我还能说什么233233233 就是让你转边权为点权之后, ...
- 【BZOJ1984】月下“毛景树” 树链剖分+线段树
[BZOJ1984]月下"毛景树" Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校 ...
- 【BZOJ-1984】月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1314 Solved: 416[Submit][Status][Discu ...
- 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”
题面:月下“毛景树” 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来,可以发现a到b节点间 ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- Bzoj 1984: 月下“毛景树” 树链剖分
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1282 Solved: 410[Submit][Status][Discu ...
随机推荐
- Entity Framework + WCF 远程调用出错
在使用Entity Framework中使用WCF,在程序中调用服务一直报错,我一直以为是WCF的哪个地方的配置有问题,找来找去,一直没有解决. 最后在网上找到一篇文章 ...
- 使用Cydia Substrate Hook Android Java世界
从来没接触过Android的HOOK,在看雪上找到了一篇HOOK 的文章,但是太复杂了,应该是本地环境问题,测试不成功. 后来搜到Cydia Substrate,看了几篇文章,进入官网查看了一下文档, ...
- Qt 解析网络数据出现ssl错误
最近写了点小东西,哈哈, 网络部分是同学帮我搞的 在编译的时候,出现了一下错误 qt.network.ssl: QSslSocket: cannot call unresolved function ...
- 阿里云DTS VS MySQLdump
云平台的到来,使得越来越多用户的数据库由云下迁到云上.对于这种情况,阿里对此提出两种方案,一种是MySQL自带的MySQLdump,另外一种就是阿里云的DTS. DTS支持异构数据源之间的数据迁移同步 ...
- Python 把两个列表遍历为一个
两个list, 有对应关系,希望同时完成遍历 用迭代器迭代的方法也不是不可以,python提供了更直观的方法: 可以使用zip把两个list打包 , 类似: list1 = [1,2,3,4] lis ...
- 常见 SQL语句使用 增删改查
一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...
- Linux SPI总线和设备驱动架构之四:SPI数据传输的队列化
我们知道,SPI数据传输可以有两种方式:同步方式和异步方式.所谓同步方式是指数据传输的发起者必须等待本次传输的结束,期间不能做其它事情,用代码来解释就是,调用传输的函数后,直到数据传输完成,函数才会返 ...
- 16常用API
常用API 今日内容介绍 u 正则表达式 u Date u DateFormat u Calendar 第1章 正则表达式 1.1 正则表达式的概念 正则表达式(英语:Regular Expressi ...
- java对象-String的用法
以某字符串结尾:“”.endwith("") 字符串比较:equals(anotherstr) 命名遵循英文语法
- 【Python】Python学习----第一模块笔记
1.python是什么? python是动态解释型的强类型定义语言. python官方版本的解释器是CPython.该解释器使用C语言开发. 当前主要使用3.x版本的python. 2.第一个pyth ...