您的位置:首页 > 其它

BZOJ3531: [Sdoi2014]旅行

2014-08-10 01:02 429 查看

3531: [Sdoi2014]旅行

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 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 6

3 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

8

9

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