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 树链剖分的更多相关文章

  1. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  2. BZOJ 4326 树链剖分+二分+差分+记忆化

    去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...

  3. BZOJ 1036 && 树链剖分

    还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...

  4. bzoj 3083 树链剖分

    首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...

  5. bzoj 4196 树链剖分 模板

    [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2135  Solved: 1232[Submit][Status][D ...

  6. BZOJ 4811 树链剖分+线段树

    思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...

  7. BZOJ 4034 树链剖分

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034 题意:中文题面 思路:树链剖分入门题. 剖分后就是一个简单的区间更新和区间求和问题. ...

  8. HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数

    用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...

  9. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

随机推荐

  1. 玩转Node.js(四)-搭建简单的聊天室

    玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...

  2. 各种网站,app的手机号绑定真坑爹

    各种网站,app的手机号绑定真坑爹,无力吐槽,哎

  3. 用node是踩过的一些坑

    1.http.request抓取数据时,response的“data”回调事件返回的数据不完整 问题原因:因为“data"事件返回是chunk,就是说是一块块连续的数据 解决的办法:在”da ...

  4. 洛谷P1378油滴扩展

    题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界. 必须等一个油滴扩展完毕才能放置下一个油滴 ...

  5. python第三天(dictionary应用)转

    1.题目: python实现英文文章中出现单词频率的统计   前言: 这道题在实际应用场景中使用比较广泛,比如统计历年来四六级考试中出现的高频词汇,记得李笑来就利用他的编程技能出版过一本背单词的畅销书 ...

  6. JAVA的文件操作【转】

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  7. VFS dup ,dup2

    Linux支持各种各样的文件系统格式,如ext2.ext3.reiserfs.FAT.NTFS.iso9660等等,不同的磁盘分区.光盘或其它存储设备都有不同的文件系统格式,然而这些文件系统都可以mo ...

  8. lintcode-133-最长单词

    133-最长单词 给一个词典,找出其中所有最长的单词. 样例 在词典 { "dog", "google", "facebook", &quo ...

  9. ArcGIS10.2中文版安装和破解教程

    http://jingyan.baidu.com/article/e73e26c0cb5c1324adb6a791.html

  10. SpringMVC-01-宏观上把握SpringMVC框架

    springmvc是一个基于mvc的web框架,是spring框架的一个模块,所以springmvc和spring无需通过中间整合层进行整合.我们先来看下spring的一个架构模型,看springmv ...