首页 > 代码库 > BZOJ3531: [Sdoi2014]旅行

BZOJ3531: [Sdoi2014]旅行

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掉了这道题
做树链剖分让我充分意识到了线段树的强大。。。真是灵活的数据结构
这题的动态开点技巧还需要慢慢品味
代码:
  1 {$M 10000000,0,maxlongint}  2 const maxn=100000+10;  3 type node1=record  4      go,next:longint;  5      end;  6      node2=record  7      l,r,mid,lch,rch,mx:longint;  8      sum:int64;  9      end; 10  11 var  e:array[0..2*maxn] of node1; 12      t:array[0..40*maxn] of node2; 13      p,fa,s,head,dep,son,top,w,c,rt:array[0..maxn] of longint; 14      i,n,m,x,y,z,sz,tot,cnt,root:longint; 15      ans:int64; 16      ch:char; 17       procedure swap(var x,y:longint); 18       var t:longint; 19       begin 20         t:=x;x:=y;y:=t; 21       end; 22      procedure insert(x,y:longint); 23       begin 24         inc(tot); 25         e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot; 26       end; 27      function min(x,y:longint):longint; 28       begin 29         if x<y then exit(x) else exit(y); 30       end; 31      function max(x,y:longint):longint; 32       begin 33         if x>y then exit(x) else exit(y); 34       end; 35 procedure dfs1(x:longint); 36  var i,j,y:longint; 37  begin 38    j:=0;s[x]:=1; 39    i:=head[x]; 40    while i<>0 do 41     begin 42      y:=e[i].go; 43      if dep[y]=0 then 44        begin 45          dep[y]:=dep[x]+1; 46          fa[y]:=x; 47          dfs1(y); 48          inc(s[x],s[y]); 49          if s[y]>s[j] then j:=y; 50        end; 51      i:=e[i].next; 52     end; 53    son[x]:=j; 54  end; 55 procedure dfs2(x,chain:longint); 56  var i,y:longint; 57  begin 58    inc(sz);p[x]:=sz;top[x]:=chain; 59    if son[x]<>0 then dfs2(son[x],chain); 60    i:=head[x]; 61    while i<>0 do 62      begin 63       y:=e[i].go; 64       if (y<>son[x]) and (y<>fa[x]) then dfs2(y,y); 65       i:=e[i].next; 66      end; 67  end; 68 procedure pushup(k:longint); 69  begin 70    with t[k] do 71     begin 72       mx:=max(t[lch].mx,t[rch].mx); 73       sum:=t[lch].sum+t[rch].sum; 74     end; 75  end; 76 procedure change(var k:longint;x,y,pos,val:longint); 77  begin 78    if k=0 then begin inc(cnt);k:=cnt;end; 79    with t[k] do 80     begin 81      l:=x;r:=y;mid:=(l+r)>>1; 82      if l=r then begin mx:=val;sum:=val;exit;end; 83      if pos<=mid then change(lch,l,mid,pos,val) 84      else change(rch,mid+1,r,pos,val); 85      pushup(k); 86     end; 87  end; 88 procedure init; 89  begin 90    readln(n,m); 91    for i:=1 to n do readln(w[i],c[i]); 92    for i:=1 to n-1 do begin readln(x,y);insert(x,y);insert(y,x);end; 93    dep[1]:=1; 94    dfs1(1); 95    dfs2(1,1); 96    cnt:=0; 97    for i:=1 to n do change(rt[c[i]],1,n,p[i],w[i]); 98  end; 99 function getmx(k,x,y:longint):longint;100  begin101    if k=0 then exit(0);102    with t[k] do103     begin104      if (l=x) and (r=y) then exit(mx);105      if y<=mid then exit(getmx(lch,x,y))106      else if x>mid then exit(getmx(rch,x,y))107      else exit(max(getmx(lch,x,mid),getmx(rch,mid+1,y)));108     end;109  end;110 function getsum(k,x,y:longint):int64;111  begin112    if k=0 then exit(0);113    with t[k] do114     begin115      if (l=x) and (r=y) then exit(sum);116      if y<=mid then exit(getsum(lch,x,y))117      else if x>mid then exit(getsum(rch,x,y))118      else exit(getsum(lch,x,mid)+getsum(rch,mid+1,y));119     end;120  end;121 procedure solvemx;122  begin123    ans:=0;124    readln(x,y);root:=rt[c[x]];125    while top[x]<>top[y] do126      begin127       if dep[top[x]]<dep[top[y]] then swap(x,y);128       ans:=max(ans,getmx(root,p[top[x]],p[x]));129       x:=fa[top[x]];130      end;131    if dep[x]>dep[y] then swap(x,y);132    ans:=max(ans,getmx(root,p[x],p[y]));133    writeln(ans);134  end;135 procedure solvesum;136  begin137    ans:=0;138    readln(x,y);root:=rt[c[x]];139    while top[x]<>top[y] do140      begin141       if dep[top[x]]<dep[top[y]] then swap(x,y);142       inc(ans,getsum(root,p[top[x]],p[x]));143       x:=fa[top[x]];144      end;145    if dep[x]>dep[y] then swap(x,y);146    inc(ans,getsum(root,p[x],p[y]));147    writeln(ans);148  end;149 procedure main;150  begin151    for i:=1 to m do152     begin153      read(ch,ch);154      case ch of155      W:begin156          readln(x,y);157          w[x]:=y;158          change(rt[c[x]],1,n,p[x],y);159          end;160      C:begin161          readln(x,y);162          change(rt[c[x]],1,n,p[x],0);163          c[x]:=y;164          change(rt[y],1,n,p[x],w[x]);165          end;166      M:solvemx;167      S:solvesum;168     end;169    end;170  end;171 begin172   assign(input,input.txt);assign(output,output.txt);173   reset(input);rewrite(output);174   init;175   main;176   close(input);close(output);177 end.    
View Code