BZOJ3531: [Sdoi2014]旅行
2014-08-10 01:02
429 查看
3531: [Sdoi2014]旅行
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 333 Solved: 197
[Submit][Status]
Description
S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
Input
输入的第一行包含整数N,Q依次表示城市数和事件数。接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。
Output
对每个QS和QM事件,输出一行,表示旅行者记下的数字。Sample Input
5 63 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4
Sample Output
89
11
3
HINT
N,Q < =10^5 , C < =10^5数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
Source
Round 1 Day 1题解:
Greens的动态开点实在不能再炫酷,真是长见识了!
终于A掉了这道题
做树链剖分让我充分意识到了线段树的强大。。。真是灵活的数据结构
这题的动态开点技巧还需要慢慢品味
代码:
{$M 10000000,0,maxlongint} const maxn=100000+10; type node1=record go,next:longint; end; node2=record l,r,mid,lch,rch,mx:longint; sum:int64; end; var e:array[0..2*maxn] of node1; t:array[0..40*maxn] of node2; p,fa,s,head,dep,son,top,w,c,rt:array[0..maxn] of longint; i,n,m,x,y,z,sz,tot,cnt,root:longint; ans:int64; 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 mx:=max(t[lch].mx,t[rch].mx); sum:=t[lch].sum+t[rch].sum; end; end; procedure change(var k:longint;x,y,pos,val:longint); begin if k=0 then begin inc(cnt);k:=cnt;end; with t[k] do begin l:=x;r:=y;mid:=(l+r)>>1; if l=r then begin mx:=val;sum:=val;exit;end; if pos<=mid then change(lch,l,mid,pos,val) else change(rch,mid+1,r,pos,val); pushup(k); end; end; procedure init; begin readln(n,m); for i:=1 to n do readln(w[i],c[i]); 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); cnt:=0; for i:=1 to n do change(rt[c[i]],1,n,p[i],w[i]); end; function getmx(k,x,y:longint):longint; begin if k=0 then exit(0); with t[k] do begin if (l=x) and (r=y) then exit(mx); if y<=mid then exit(getmx(lch,x,y)) else if x>mid then exit(getmx(rch,x,y)) else exit(max(getmx(lch,x,mid),getmx(rch,mid+1,y))); end; end; function getsum(k,x,y:longint):int64; begin if k=0 then exit(0); with t[k] do begin if (l=x) and (r=y) then exit(sum); if y<=mid then exit(getsum(lch,x,y)) else if x>mid then exit(getsum(rch,x,y)) else exit(getsum(lch,x,mid)+getsum(rch,mid+1,y)); end; end; procedure solvemx; begin ans:=0; readln(x,y);root:=rt[c[x]]; while top[x]<>top[y] do begin if dep[top[x]]<dep[top[y]] then swap(x,y); ans:=max(ans,getmx(root,p[top[x]],p[x])); x:=fa[top[x]]; end; if dep[x]>dep[y] then swap(x,y); ans:=max(ans,getmx(root,p[x],p[y])); writeln(ans); end; procedure solvesum; begin ans:=0; readln(x,y);root:=rt[c[x]]; while top[x]<>top[y] do begin if dep[top[x]]<dep[top[y]] then swap(x,y); inc(ans,getsum(root,p[top[x]],p[x])); x:=fa[top[x]]; end; if dep[x]>dep[y] then swap(x,y); inc(ans,getsum(root,p[x],p[y])); writeln(ans); end; procedure main; begin for i:=1 to m do begin read(ch,ch); case ch of 'W':begin readln(x,y); w[x]:=y; change(rt[c[x]],1,n,p[x],y); end; 'C':begin readln(x,y); change(rt[c[x]],1,n,p[x],0); c[x]:=y; change(rt[y],1,n,p[x],w[x]); end; 'M':solvemx; 'S':solvesum; end; end; end; begin assign(input,'input.txt');assign(output,'output.txt'); reset(input);rewrite(output); init; main; close(input);close(output); end.
View Code
相关文章推荐
- [Sdoi 2014] bzoj3531 旅行 [树链剖分]
- BZOJ3531 【Sdoi2014】旅行
- bzoj3531: [Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行 树链剖分 线段树
- bzoj3531【SDOI2014】旅行
- BZOJ3531 [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行——树剖+动态开点线段树
- bzoj3531[Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行(树链剖分+动态开点线段树)
- bzoj3531 [Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行 树链剖分+动态开线段树
- bzoj3531 [Sdoi2014]旅行 【树链剖分+线段树动态开点】
- 【BZOJ3531】旅行(SDOI2014)-树链剖分+动态加点线段树
- BZOJ3531: [Sdoi2014]旅行
- Bzoj3531:[Sdoi2014]旅行:树链剖分+动态开点线段树
- BZOJ3531 [Sdoi2014]旅行 【树剖 + 线段树】
- BZOJ3531: [Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行