BZOJ2243: [SDOI2011]染色
2014-08-08 19:32
417 查看
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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 52 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
31
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
相关文章推荐
- 洛谷 P2486 BZOJ 2243 [SDOI2011]染色
- 【bzoj2243】[SDOI2011]染色(树链剖分)
- BZOJ 2243: [SDOI2011]染色 树链剖分
- 【BZOJ 2243】【SDOI 2011】染色【树链剖分】
- bzoj2243【SDOI2011】染色
- BZOJ2243 [SDOI2011]染色 题解&代码
- 【树链剖分】bzoj2243 [SDOI2011]染色
- BZOJ 2243: [SDOI2011]染色
- bzoj2243 SDOI2011 染色 树链剖分
- [SDOI2011]染色 bzoj 2243 树链剖分
- 【bzoj2243】[SDOI2011]染色
- bzoj 2243: [SDOI2011]染色 树链剖分+线段树
- Bzoj 2243: [SDOI2011]染色(树链剖分+线段树)
- BZOJ 2243 [SDOI2011] 染色
- BZOJ 2243: [SDOI2011]染色 【树链剖分】
- 【bzoj2243】【sdoi2011】染色【树链剖分】
- bzoj2243 [SDOI2011]染色
- 【bzoj2243】 [SDOI2011]染色
- BZOJ-2243: [SDOI2011]染色 (树链剖分 入门题 线段树 区间修改查询 维护端点值)
- BZOJ2243: [SDOI2011]染色