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& ...
随机推荐
- ionic 入口禁止加载其他页面
.state('memberOrders', { prefetchTemplate: false, url: '/memberOrders', templateUrl: '/MemberOrders' ...
- ACE_Select_Reactor_T 介绍 (2)
本章目录 ACE_Select_Reactor_T 介绍 类继承图 类协作图 类主要成员变量 事件处理函数调用图 事件处理主流程 handle_events 函数流程 handle_events_i ...
- 解决Unbuntu终端菱形乱码问题
原因:安装时为了学习方便选择中文安装,其字符编码相关配置如下(在/etc/default/locale中) LANG="Zh_CN.UTF-8 "LANGUAGE="zh ...
- 机器学习性能指标精确率、召回率、F1值、ROC、PRC与AUC--周振洋
机器学习性能指标精确率.召回率.F1值.ROC.PRC与AUC 精确率.召回率.F1.AUC和ROC曲线都是评价模型好坏的指标,那么它们之间有什么不同,又有什么联系呢.下面让我们分别来看一下这几个指标 ...
- HDU 3699 A hard Aoshu Problem(暴力枚举)(2010 Asia Fuzhou Regional Contest)
Description Math Olympiad is called “Aoshu” in China. Aoshu is very popular in elementary schools. N ...
- sql 条件插入
原普通插入语句: insert into seriestable_upload values(New.SeriesID,0); 加条件后:(当不存在该条数据插入) insert into custom ...
- 自定义Json格式
老铁们都知道,一般的json格式就是键值对格式,在一些特定的框架或者系统中,会用到自定义格式的json文件,假设我们要得到的特定格式json格式如下: {"A":"2&q ...
- Java语言课程设计
一.项目简介 本实验是对图形用户界面,布局管理器的综合应用,理解Java的处理机制,编写独立运行的窗口 二.项目采用技术 GUI,JAVA 三.功能需求分析 1.使用用户图形界面 2.能够实现年月份的 ...
- thinkphp3.2 常用单字母函数
U函数:用来生成url U('地址表达式',['参数'],['伪静态后缀'],['显示域名'] 例如: U('Blog/read?id=1') // 生成Blog控制器的read操作 并且id为1的U ...
- SQL 取数值小数后两位,但不四舍五入
select round('1.67789',2,1) /* 1.67*/