bzoj 2243 树链剖分
2013-11-19 16:21
原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243
树链剖分,用线段树记录该区间的颜色段数,左右端点颜色数,然后就OK了
//By BLADEVIL
type
rec =record
sum, left, right, succ, pred :longint;
lazy :longint;
end; var
n :longint;
pre, other :array[..] of longint;
last :array[..] of longint;
m :longint;
color :array[..] of longint;
father, size, max_son :array[..] of longint;
dep, top, a, num :array[..] of longint;
tot :longint;
flag :array[..] of boolean;
l :longint;
t :array[..] of rec; procedure swap(var a,b:longint);
var
c :longint;
begin
c:=a; a:=b; b:=c;
end; procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end; procedure dfs(x:longint);
var
q, p :longint;
begin
size[x]:=;
q:=last[x];
while q<> do
begin
p:=other[q];
if not flag[p] then
begin
father[p]:=x;
flag[p]:=true;
dfs(p);
inc(size[x],size[p]);
if size[max_son[x]]<size[p] then max_son[x]:=p;
end;
q:=pre[q];
end;
end; procedure make(x,t,depth:longint);
var
q, p :longint;
begin
inc(tot);
num[x]:=tot;
top[x]:=t;
a[tot]:=color[x];
dep[x]:=depth;
if (max_son[x]<>) and (not flag[max_son[x]]) then
begin
flag[max_son[x]]:=true;
make(max_son[x],t,depth);
end;
q:=last[x];
while q<> do
begin
p:=other[q];
if not flag[p] then
begin
flag[p]:=true;
make(p,p,depth+);
end;
q:=pre[q];
end;
end; procedure build(x,l,r:longint);
var
mid :longint;
begin
t[x].left:=l; t[x].right:=r;
if l=r then
begin
t[x].sum:=;
t[x].succ:=a[l];
t[x].pred:=a[l];
exit;
end;
mid:=(l+r) div ;
build(x*,l,mid);
build(x*+,mid+,r);
t[x].succ:=t[x*].succ;
t[x].pred:=t[x*+].pred;
if t[x*].pred=t[x*+].succ then
t[x].sum:=t[x*].sum+t[x*+].sum- else
t[x].sum:=t[x*].sum+t[x*+].sum;
end; procedure init;
var
i :longint;
x, y :longint; begin
read(n,m);
for i:= to n do read(color[i]);
for i:= to n- do
begin
read(x,y);
connect(x,y);
connect(y,x);
end;
flag[]:=true;
dfs();
fillchar(flag,sizeof(flag),false);
flag[]:=true;
make(,,);
build(,,n);
end; procedure change(x,l,r,z:longint);
var
mid :longint;
begin
if t[x].lazy<> then
begin
t[x*].lazy:=t[x].lazy;
t[x*].sum:=;
t[x*].succ:=t[x].lazy;
t[x*].pred:=t[x].lazy;
t[x*+].lazy:=t[x].lazy;
t[x*+].sum:=;
t[x*+].succ:=t[x].lazy;
t[x*+].pred:=t[x].lazy;
t[x].lazy:=;
end;
if (t[x].left=l) and (t[x].right=r) then
begin
t[x].lazy:=z;
t[x].sum:=;
t[x].succ:=z;
t[x].pred:=z;
exit;
end;
with t[x] do mid:=(left+right) div ;
if mid<l then change(x*+,l,r,z) else
if mid>=r then change(x*,l,r,z) else
begin
change(x*,l,mid,z);
change(x*+,mid+,r,z);
end;
t[x].succ:=t[x*].succ;
t[x].pred:=t[x*+].pred;
if t[x*].pred=t[x*+].succ then
t[x].sum:=t[x*].sum+t[x*+].sum- else
t[x].sum:=t[x*].sum+t[x*+].sum;
end; function ask(x,l,r:longint):rec;
var
mid :longint;
t1, t2 :rec;
begin
if t[x].lazy<> then
begin
t[x*].lazy:=t[x].lazy;
t[x*].sum:=;
t[x*].succ:=t[x].lazy;
t[x*].pred:=t[x].lazy;
t[x*+].lazy:=t[x].lazy;
t[x*+].sum:=;
t[x*+].succ:=t[x].lazy;
t[x*+].pred:=t[x].lazy;
t[x].lazy:=;
end; if (t[x].left=l) and (t[x].right=r) then
begin
ask.succ:=t[x].succ;
ask.pred:=t[x].pred;
ask.sum:=t[x].sum;
exit;
end; with t[x] do mid:=(left+right) div ;
if mid<l then
begin
t2:=ask(x*+,l,r);
ask.succ:=t2.succ;
ask.pred:=t2.pred;
ask.sum:=t2.sum
end else
if mid>=r then
begin
t1:=ask(x*,l,r);
ask.succ:=t1.succ;
ask.pred:=t1.pred;
ask.sum:=t1.sum
end else
begin
t1:=ask(x*,l,mid);
t2:=ask(x*+,mid+,r);
ask.succ:=t1.succ;
ask.pred:=t2.pred;
if t1.pred=t2.succ then
ask.sum:=t1.sum+t2.sum- else
ask.sum:=t1.sum+t2.sum;
end;
end; procedure paint(x,y,z:longint);
begin
if dep[x]>dep[y] then swap(x,y);
while dep[x]<dep[y] do
begin
change(,num[top[y]],num[y],z);
y:=father[top[y]];
end;
while top[x]<>top[y] do
begin
change(,num[top[x]],num[x],z);
change(,num[top[y]],num[y],z);
x:=father[top[x]];
y:=father[top[y]];
end;
x:=num[x];
y:=num[y];
if x>y then swap(x,y);
change(,x,y,z);
end; procedure query(x,y:longint);
var
ans :longint;
a, b :longint;
begin
ans:=;
if dep[x]>dep[y] then swap(x,y);
while dep[x]<dep[y] do
begin
ans:=ans+ask(,num[top[y]],num[y]).sum;
a:=ask(,num[top[y]],num[top[y]]).succ;
b:=ask(,num[father[top[y]]],num[father[top[y]]]).pred;
if a=b then dec(ans);
y:=father[top[y]];
end;
while top[x]<>top[y] do
begin
ans:=ans+ask(,num[top[y]],num[y]).sum;
a:=ask(,num[top[y]],num[top[y]]).succ;
b:=ask(,num[father[top[y]]],num[father[top[y]]]).pred;
if a=b then dec(ans);
ans:=ans+ask(,num[top[x]],num[x]).sum;
a:=ask(,num[top[x]],num[top[x]]).succ;
b:=ask(,num[father[top[x]]],num[father[top[x]]]).pred;
if a=b then dec(ans);
x:=father[top[x]];
y:=father[top[y]];
end;
x:=num[x];
y:=num[y];
if x>y then swap(x,y);
ans:=ans+ask(,x,y).sum;
writeln(ans);
end; procedure main;
var
i :longint;
c :char;
x, y, z :longint; begin
readln;
for i:= to m do
begin
read(c);
if c='Q' then
begin
readln(x,y);
query(x,y)
end else
begin
readln(x,y,z);
paint(x,y,z);
end;
end;
end; begin
init;
main;
end.
bzoj 2243 树链剖分的更多相关文章
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- BZOJ 4326 树链剖分+二分+差分+记忆化
去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...
- BZOJ 1036 && 树链剖分
还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...
- bzoj 3083 树链剖分
首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...
- bzoj 4196 树链剖分 模板
[Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2135 Solved: 1232[Submit][Status][D ...
- BZOJ 4811 树链剖分+线段树
思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...
- BZOJ 4034 树链剖分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034 题意:中文题面 思路:树链剖分入门题. 剖分后就是一个简单的区间更新和区间求和问题. ...
- HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数
用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...
- BZOJ 2286 树链剖分+DFS序+虚树+树形DP
第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...
随机推荐
- iOS笔记054 - 核心动画
注意事项 :locationInView和translationInView // 返回相对于控件自身内部触摸点的位置 [pan locationInView:self]; // 返回两个触摸点之间的 ...
- 「日常训练」 Finite or not? (CFR483D2C)
题意(Codeforces 984C) 给定p,q,b" role="presentation">p,q,bp,q,b,问pq" role="p ...
- Vm Ubuntu 文件共享问题
其实也是差不多的,就是需要重新安装一次工具 ,自己安装有问题,自己在手动安装一次就好了 下面是一个我的参考文章 http://blog.csdn.net/zz962/article/details/7 ...
- 解决Unbuntu终端菱形乱码问题
原因:安装时为了学习方便选择中文安装,其字符编码相关配置如下(在/etc/default/locale中) LANG="Zh_CN.UTF-8 "LANGUAGE="zh ...
- xadmin站点管理面样样式控制
xadmin可以使用的页面样式控制基本与Django原生的admin一直. list_display 控制列表展示的字段 search_fields 控制可以通过搜索框搜索的字段名称,xadmin使用 ...
- Spring Boot 学习随记
微架构的思想在各大互联网公司越来越普及,特此记录Spring Boot的一些细节问题! 网上spring-boot的教程一堆一堆,就没有必要再详细记录了 1:建议通过Idea 来创建spring-bo ...
- c free 使用MSDN library定制
为了不使用vc6但是还要使用visual assist的各种自动功能,决定使用c free ,但是怎么调用微软的MSDN library呢,我目前使用的版本是MSDN 1.5精简版bing自动翻译的. ...
- weak_ptr打破环状引用
转自:http://blog.csdn.net/malong777/article/details/48974559 weak_ptr是一种不控制对象生存周期的智能指针,它指向一个shared_ptr ...
- sping事务的理解
阅读数:2020 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤 ...
- sendto函数的坑
测试unix数据报套接字时,一个程序收,一个程序发,分别绑定自己的socket.结果在收的部分,返回的发送方的地址总是空的,但是返回的地址长度又是对的. ) { bzero(&clientad ...