您的位置:首页 > 其它

BZOJ2243: [SDOI2011]染色

2014-08-08 19:32 417 查看

2243: [SDOI2011]染色

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 1934 Solved: 775
[Submit][Status]

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]之间。

Source

第一轮day1

题解:
强大的树链剖分!强大的线段树!
原来统计一段序列被分为几段是可以分治的,一直想这个想了好久。。。
通过这题,学到了几点:
1.线段树
pushdown操作是在查询到k,需要继续向下时调用
pushup不管什么操作,完了之后调用一次
2.树链剖分
确认算法没错肯定是哪儿犯了sb错误。。。
现在感觉树链剖分也是蛮好写的,虽然代码蛮长
代码:

{$M 10000000,0,maxlongint}
const maxn=100000+100;
type node1=record
go,next:longint;
end;
node2=record
l,r,lx,rx,num,mid,tag:longint;
end;

var  e:array[0..2*maxn] of node1;
t:array[0..4*maxn] of node2;
p,a,v,fa,s,head,dep,son,top:array[0..maxn] of longint;
i,n,m,x,y,z,sz,ans,tot:longint;
ch:char;
procedure swap(var x,y:longint);
var t:longint;
begin
t:=x;x:=y;y:=t;
end;
procedure insert(x,y:longint);
begin
inc(tot);
e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
procedure dfs1(x:longint);
var i,j,y:longint;
begin
j:=0;s[x]:=1;
i:=head[x];
while i<>0 do
begin
y:=e[i].go;
if dep[y]=0 then
begin
dep[y]:=dep[x]+1;
fa[y]:=x;
dfs1(y);
inc(s[x],s[y]);
if s[y]>s[j] then j:=y;
end;
i:=e[i].next;
end;
son[x]:=j;
end;
procedure dfs2(x,chain:longint);
var i,y:longint;
begin
inc(sz);p[x]:=sz;top[x]:=chain;
if son[x]<>0 then dfs2(son[x],chain);
i:=head[x];
while i<>0 do
begin
y:=e[i].go;
if (y<>son[x]) and (y<>fa[x]) then dfs2(y,y);
i:=e[i].next;
end;
end;
procedure pushup(k:longint);
begin
with t[k] do
begin
num:=t[k<<1].num+t[k<<1+1].num-ord(t[k<<1].rx=t[k<<1+1].lx);
lx:=t[k<<1].lx;rx:=t[k<<1+1].rx;
end;
end;

procedure build(k,x,y:longint);
begin
with t[k] do
begin
l:=x;r:=y;mid:=(l+r)>>1;tag:=0;
if l=r then begin lx:=a[l];rx:=a[l];num:=1;exit;end;
build(k<<1,l,mid);build(k<<1+1,mid+1,r);
pushup(k);
end;
end;

procedure init;
begin
readln(n,m);
for i:=1 to n do read(v[i]);readln;
for i:=1 to n-1 do begin readln(x,y);insert(x,y);insert(y,x);end;
dep[1]:=1;
dfs1(1);
dfs2(1,1);
for i:=1 to n do a[p[i]]:=v[i];
build(1,1,n);
end;
procedure same(k,val:longint);
begin
with t[k] do
begin
tag:=val;lx:=val;rx:=val;num:=1;
end;
end;

procedure pushdown(k:longint);
begin
with t[k] do
begin
if (tag=0) or (l=r) then exit;
same(k<<1,tag);same(k<<1+1,tag);
tag:=0;
end;
end;

procedure change(k,x,y,z:longint);
begin
with t[k] do
begin
pushdown(k);
if (l=x) and (r=y) then begin same(k,z);exit;end;
pushdown(k);
if y<=mid then change(k<<1,x,y,z)
else if x>mid then change(k<<1+1,x,y,z)
else
begin
change(k<<1,x,mid,z);
change(k<<1+1,mid+1,y,z);
end;
pushup(k);
end;
end;
function query(k,x,y:longint):longint;
begin
with t[k] do
begin
if (l=x) and (r=y) then exit(num);
pushdown(k);
if y<=mid then exit(query(k<<1,x,y))
else if x>mid then exit(query(k<<1+1,x,y))
else exit(query(k<<1,x,mid)+query(k<<1+1,mid+1,y)-ord(t[k<<1].rx=t[k<<1+1].lx));
pushup(k);
end;
end;
function get(k,x:longint):longint;
begin
with t[k] do
begin
if l=r then exit(lx);
pushdown(k);
if x<=mid then exit(get(k<<1,x)) else exit(get(k<<1+1,x));
pushup(k);
end;
end;

procedure solvechange;
begin
readln(x,y,z);
while top[x]<>top[y] do
begin
if dep[top[x]]<dep[top[y]] then swap(x,y);
change(1,p[top[x]],p[x],z);
x:=fa[top[x]];
end;
if dep[x]>dep[y] then swap(x,y);
change(1,p[x],p[y],z);
end;
procedure getans;
begin
ans:=0;
readln(x,y);
while top[x]<>top[y] do
begin
if dep[top[x]]<dep[top[y]] then swap(x,y);
inc(ans,query(1,p[top[x]],p[x]));
dec(ans,ord(get(1,p[top[x]])=get(1,p[fa[top[x]]])));
x:=fa[top[x]];
end;
if dep[x]>dep[y] then swap(x,y);
inc(ans,query(1,p[x],p[y]));
writeln(ans);
end;

procedure main;
begin
for i:=1 to m do
begin
read(ch);
if ch='C' then solvechange
else getans;
end;
end;
begin
assign(input,'input.txt');assign(output,'output.txt');
reset(input);rewrite(output);
init;
main;
close(input);close(output);
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: