[SDOI2011]染色
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
3
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

分析:

树链剖分后用线段树维护数据,还是比较好的一道题。

树链剖分的第一个dfs要求出各个点的深度d,父节点fa,子树节点数sz,重儿子son,第二个dfs求出每个点在序列中的位置id,所在路径顶端节点编号top。

第二个dfs就是用来剖分路径的,要注意必须先对重儿子处理,只有这样一条路径的点在序列上才是连续的,这样才能用线段树维护。

然后就是线段树维护了, 不要忘记修改x到y的权值要用id[x]和id[y]表示,另外注意任何对线段树的操作必须先下传懒惰标记。

在查询时由于要跨过多条路径,相邻两个路径相接的地方颜色相同的情况也要判断。

代码:

program putcolor;
type
thing=record
l,r,v,s,e:longint;
end;
point=^node;
node=record
x:longint; next:point;
end;
var
a:array[..]of point;
dat:array[..]of thing;
sz,son,id,fa,v,b,d,top:array[..]of longint;
n,i,m,len:longint;
procedure add(x,y:longint);
var p:point;
begin
new(p); p^.x:=y; p^.next:=a[x]; a[x]:=p;
end;
procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end;
procedure dfs1(x:longint);
var y:longint; p:point;
begin
new(p); p:=a[x]; sz[x]:=;
while p<>nil do
begin
if p^.x=fa[x] then begin p:=p^.next; continue; end;
y:=p^.x; fa[y]:=x; d[y]:=d[x]+;
dfs1(y);
inc(sz[x],sz[y]); if sz[y]>sz[son[x]] then son[x]:=y;
p:=p^.next;
end;
end;
procedure dfs2(x,k:longint);
var i:longint; p:point;
begin
inc(len); id[x]:=len; b[len]:=v[x]; top[x]:=k;
if son[x]> then dfs2(son[x],k);
new(p); p:=a[x];
while p<>nil do
begin
if (p^.x<>fa[x])and(p^.x<>son[x]) then dfs2(p^.x,p^.x);
p:=p^.next;
end;
end;
procedure down(p,x,y:longint);
var l,r,v:longint;
begin
if x=y then exit;
l:=p*; r:=p*+; v:=dat[p].e;
dat[l].l:=v; dat[l].r:=v; dat[l].s:=;dat[l].e:=v;
dat[r].l:=v; dat[r].r:=v; dat[r].s:=;dat[r].e:=v;
dat[p].e:=-;
end;
procedure update(p,x,y:longint);
var l,r:longint;
begin
if x=y then exit;
l:=p*; r:=p*+;
dat[p].l:=dat[l].l; dat[p].r:=dat[r].r;
dat[p].s:=dat[l].s+dat[r].s;
if dat[l].r=dat[r].l then dec(dat[p].s);
end;
procedure build(p,l,r:longint);
var mid:longint;
begin
dat[p].s:=; dat[p].e:=-;
if l=r then exit;
mid:=(l+r) div ;
build(p*,l,mid); build(p*+,mid+,r);
end;
procedure change(x,y,p,l,r,v:longint);
var mid:longint;
begin
if dat[p].e>= then down(p,l,r);
if (x<=l)and(r<=y) then
begin dat[p].l:=v; dat[p].r:=v; dat[p].s:=; dat[p].e:=v; end else
begin
mid:=(l+r) div ;
if x<=mid then change(x,y,p*,l,mid,v);
if y>mid then change(x,y,p*+,mid+,r,v);
update(p,l,r);
end;
end;
function query(x,y,p,l,r:longint):longint;
var mid,ans:longint;
begin
if (x<=l)and(r<=y) then exit(dat[p].s)
else
begin
mid:=(l+r) div ;if dat[p].e>= then down(p,l,r); ans:=;
if x<=mid then ans:=query(x,y,p*,l,mid);
if y>mid then inc(ans,query(x,y,p*+,mid+,r));
if (x<=mid)and(y>mid) then
if dat[p*].r=dat[p*+].l then dec(ans);
exit(ans);
end;
end;
function get(p,l,r,x:longint):longint;
var mid:longint;
begin
if dat[p].e>= then down(p,l,r);
if l=x then exit(dat[p].l);
mid:=(l+r) div ;
if x<=mid then exit(get(p*,l,mid,x));
if x>mid then exit(get(p*+,mid+,r,x));
end;
procedure solvechange(x,y,z:longint);
var fx,fy,t,ans:longint;
begin
fx:=top[x]; fy:=top[y]; ans:=;
while fx<>fy do
begin
if d[fx]<d[fy] then begin swap(x,y); swap(fx,fy);; end;
change(id[fx],id[x],,,n,z);
x:=fa[fx]; fx:=top[x];
end;
if d[x]>d[y] then swap(x,y);
change(id[x],id[y],,,n,z);
end;
function solvequery(x,y:longint):longint;
var fx,fy,t,ans:longint;
begin
fx:=top[x]; fy:=top[y]; ans:=;
while fx<>fy do
begin
if d[fx]<d[fy] then begin swap(x,y); swap(fx,fy); end;
inc(ans,query(id[fx],id[x],,,n));
if get(,,n,id[fx])=get(,,n,id[fa[fx]]) then dec(ans);
x:=fa[fx]; fx:=top[x];
end;
if d[x]>d[y] then swap(x,y);
inc(ans,query(id[x],id[y],,,n));
exit(ans);
end;
procedure solve;
var i,x,y,z:longint; c:char;
begin
build(,,n);
for i:= to n do change(id[i],id[i],,,n,v[i]);
for i:= to m do
begin
read(c);
if c='C' then begin read(x,y,z); solvechange(x,y,z); end
else begin read(x,y); writeln(solvequery(x,y)); end;
readln;
end;
end;
procedure int;
var i,x,y:longint; p:point;
begin
readln(n,m);
for i:= to n do read(v[i]);
for i:= to n- do
begin
readln(x,y);
add(x,y); add(y,x);
end;
end;
begin
int;
dfs1();dfs2(,);
solve;
end.

BZOJ 2243:染色(树链剖分+区间合并线段树)的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  2. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  3. bzoj2243树链剖分+区间合并

    树链上区间合并的问题比区间修改要复杂,因为每一条重链在线段树上分布一般都是不连续的,所以在进行链上操作时要手动将其合并起来,维护两个端点值 处理时的方向问题:lca->u是一个方向,lca-&g ...

  4. HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值

    Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  5. LOJ2269 [SDOI2017] 切树游戏 【FWT】【动态DP】【树链剖分】【线段树】

    题目分析: 好题.本来是一道好的非套路题,但是不凑巧的是当年有一位国家集训队员正好介绍了这个算法. 首先考虑静态的情况.这个的DP方程非常容易写出来. 接着可以注意到对于异或结果的计数可以看成一个FW ...

  6. [GDOI2016] 疯狂动物园 [树链剖分+可持久化线段树]

    题面 太长了,而且解释的不清楚,我来给个简化版的题意: 给定一棵$n$个点的数,每个点有点权,你需要实现以下$m$个操作 操作1,把$x$到$y$的路径上的所有点的权值都加上$delta$,并且更新一 ...

  7. HYSBZ 4034 【树链剖分】+【线段树 】

    <题目链接> 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权值.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...

  8. HDU 3966 Aragorn's Story(模板题)【树链剖分】+【线段树】

    <题目链接> 题目大意: 给定一颗带点权的树,进行两种操作,一是给定树上一段路径,对其上每个点的点权增加或者减少一个数,二是对某个编号点的点权进行查询. 解题分析: 树链剖分的模板题,还不 ...

  9. 焦作网络赛E-JiuYuanWantstoEat【树链剖分】【线段树】

    You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she wil ...

随机推荐

  1. Nginx源码安装及调优配置(转)

      导读 由于Nginx本身的一些优点,轻量,开源,易用,越来越多的公司使用nginx作为自己公司的web应用服务器,本文详细介绍nginx源码安装的同时并对nginx进行优化配置. Nginx编译前 ...

  2. 从暴力匹配到KMP算法

    前言 现在有两个字符串:\(s1\)和\(s2\),现在要你输出\(s2\)在\(s1\)当中每一次出现的位置,你会怎么做? 暴力匹配算法 基本思路 用两个指针分别指向当前匹配到的位置,并对当前状态进 ...

  3. 2018.5.22 Oracle安装配置在虚拟机中外部电脑连接服务

    1.拷贝老师的集成文件(win系统和oracle服务) 2.安装虚拟机,并且打开镜像文件 3.启动监听程序(实例服务[自动].监听服务) 4.查看虚拟机ip,此ip要主机ip在同一个网段 5.检查虚拟 ...

  4. 网络编程——网络模型和InetAddress类

    第1章 网络通信协议 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样.在计算机网络中,这些连接和 ...

  5. C# 界面跳转-登陆之后跳转至主窗口

    在登陆按钮验证成功之后可以将会话结果改为OK //验证通过之后将对话结果设置为OK(之后会载入主界面) this.DialogResult = DialogResult.OK; this.Dispos ...

  6. 2019 ACM-ICPC全国邀请赛(西安) M.Travel 二分+判联通

    https://nanti.jisuanke.com/t/39280 讲道理这题写bfs求最大边权限制下从1到n的最短步数,然后二分判一下就行了. 然鹅我还是直接套了dij,一开始纠结dij能不能过, ...

  7. mysql基础,数据表的类型

  8. 5-3 time模块

    1.取当前时间戳和当前格式化时间 import time1 # 以时间戳的形式打印当前时间 1543849862 print(int(time.time()))#时间戳 # 取当前格式化好的时间 20 ...

  9. 分享 php array_column 函数 无法在低版本支持的 修改

    function i_array_column($input, $columnKey, $indexKey=null){ if(!function_exists('array_column')){ $ ...

  10. day 85 Vue学习七之vue-cookie

      Vue学习七之vue-cookie   通过vue如何操作cookie呢 参考链接:https://www.jianshu.com/p/535b53989b39 第一步:安装vue-cookies ...