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. 【连载】Maven系列(四)——配置私服

    相关文章 1.<用起来超爽的Maven——入门篇> 2.<用起来超爽的Maven——进阶篇> 3.<Maven系列(三) 进阶> 一.为什么需要私服 有些公司并不提 ...

  2. Qt Qwdget 汽车仪表知识点拆解5 标题栏图标闪烁

    先贴上效果图,注意,没有写逻辑,都是乱动的 看下最上面的部分,有一些仪表图标在闪烁,如果一个一个写,也是可以实现的,不过感觉要累死的节奏 这里我写了一个我自己的Label,完了把把这些QLabel提升 ...

  3. golang交叉编译笔记

    GOOS:目标平台的操作系统(darwin.freebsd.linux.windows) GOARCH:目标平台的体系架构(386.amd64.arm) Mac 下编译 Linux 和 Windows ...

  4. 使用JDK的keytool生成Android签名证书

    生成证书:keytool -genkey -alias [yourapp] -keyalg RSA -validity 20000 -keystore [yourapp].keystore 输入key ...

  5. 扩展欧几里得 求ax+by == n的非负整数解个数

    求解形如ax+by == n (a,b已知)的方程的非负整数解个数时,需要用到扩展欧几里得定理,先求出最小的x的值,然后通过处理剩下的区间长度即可得到答案. 放出模板: ll gcd(ll a, ll ...

  6. SPOJ 3978 Distance Query(tarjan求LCA)

    The traffic network in a country consists of N cities (labeled with integers from 1 to N) and N-1 ro ...

  7. Python如何进行中文注释

    最近,由于实习工作的需要,开始接触Python,但是第一个大的脚本写下来之后,连中文注释都没办法加,很郁闷,遂在网上找解决办法,在Python 官网上看到这个页面:http://www.python. ...

  8. BZOJ4591 SHOI2015超能粒子炮·改(卢卡斯定理+数位dp)

    注意到模数很小,容易想到使用卢卡斯定理,即变成一个2333进制数各位组合数的乘积.对于k的限制容易想到数位dp.可以预处理一发2333以内的组合数及组合数前缀和,然后设f[i][0/1]为前i位是否卡 ...

  9. JSP语法,运行机理等

    JSP是几年前就接触了,但是用归用,很多实际的意义含义等还是不太明白,借此机会,梳理一下. 1.JSP运行原理:当浏览器web应用服务器请求一个JSP页面时,Web应用服务器将其转换成一个Servle ...

  10. Java Web开发之路(一)——环境配置

    1. 下载JDK(Java Development Kit)工具包.其中包括运行Java程序所必须的JRE环境及开发过程中常用的库文件. (JDK与JRE的关系: JDK是Java的开发环境,在编写J ...