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& ...
随机推荐
- 失败的尝试,使用继承扩展数组,以及ES6的必要性
我们都知道直接在原生对象上扩展对象是很不好的.所以prototype这样的库广受非议. 一些库,比如lodash采用了工具包形式的扩展方式,绕开了对象的继承. 由于es6的class的出现,我尝试以A ...
- linux中wget 、apt-get、yum rpm区别
wget 类似于迅雷,是一种下载工具, 通过HTTP.HTTPS.FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理名字是World Wide Web”与“get”的结合. yum: 是r ...
- React开发时候注意点
JSX 使用jsx的使用,用一个{}包裹起来,例如 const method = {<div> 123 </div>} 使用()小括号,防止分号自动插入 const eleme ...
- vim字符编码
今天我在用vim新建中文文件的时候遇到保存好出现乱码的问题,经过一波百度, :set encoding=utf-8 :set fileencodings=ucs-bom,utf-8,cp936 :se ...
- Python调用MySQL的一些用法小结
目标:1个excel表内容导入到数据库中,例如:原始excel文件为 aaa.xls 首先:将aaa.xls 转换成aaa.txt ,注意当文件中含有中文字符时,可以通过notepad++打开,在“格 ...
- iOS-登录发送验证码时60秒倒计时,直接用
__block NSInteger timeout= ; //倒计时时间 KWeakSelf dispatch_queue_t queue = dispatch_get_global_queue(DI ...
- ArcGIS Engine开发中利用GP工具时常出现的错误
在用GP工具的时候常常会碰到这个错误: 调用 GP 对 COM 组件的调用返回了错误 HRESULT E_FAIL 解决方案: 这种情况一般有两种可能. 1.AE程序的license的级别不够. 2. ...
- 使用PHP静态变量当缓存的方法
下面这个PHP的代码实例,功能是帮助用户重置密码,requestResetPassword是接收用户重置密码的请求并且做了相应的检查.为了更好的复用性,我将重置密码的操作单独分配到一个新的resetP ...
- Eclipse的优化方案
General > Startup and Shutdown : 移除所有在启动时加载的插件. General > Editors > Text Editors > Spell ...
- Elasticsearch中的分词器比较及使用方法
Elasticsearch 默认分词器和中分分词器之间的比较及使用方法 https://segmentfault.com/a/1190000012553894 介绍:ElasticSearch 是一个 ...