[BZOJ3531] SDOI2014 树链剖分+动态开点线段树

来源:互联网 发布:金蝶软件数据库安装 编辑:程序博客网 时间:2024/05/29 09:25

首先发现是一棵树,想到树链剖分来维护路径。
但是如何把不同宗教的点分开计数?想到给每一个宗教开一颗线段树来维护,因为总共点数只有10^5个,可以采取动态开点来保证内存不超。
代码

type  xtree=^xtreenode;  xtreenode=record    max,sum,l,r:longint;    ls,rs:xtree;  end;  edge=^edgenode;  edgenode=record    t:longint;    next:edge;  end;var  n,q,i,j,u,v,time,ans,ck,x,y:longint;  c1:char;  w,c,dfn,fdfn,deep,size,head,hs,fa:array[0..100100]of longint;  con:array[1..100100]of edge;  xtr:array[1..100100]of xtree;procedure ins(x,y:longint);var  p:edge;begin  new(p);  p^.t:=y;  p^.next:=con[x];  con[x]:=p;end;function maxx(x,y:longint):longint;begin  if x>y then exit(x)  else exit(y);end;procedure outp(x:xtree);begin  if x=nil then exit;  writeln(x^.l,' ',x^.r,' ',x^.max,' ',x^.sum);  outp(x^.ls);  outp(x^.rs);end;procedure dfs1(v:longint);var  p:edge;  max,maxi:longint;begin  size[v]:=1;  deep[v]:=deep[fa[v]]+1;  p:=con[v];  max:=0;  maxi:=0;  while p<>nil do  begin    if p^.t<>fa[v] then    begin      fa[p^.t]:=v;      dfs1(p^.t);      if size[p^.t]>max then begin max:=size[p^.t]; maxi:=p^.t end;      size[v]:=size[v]+size[p^.t];    end;    p:=p^.next;  end;  hs[v]:=maxi;end;procedure dfs2(v:longint);var  p:edge;begin  inc(time);  dfn[v]:=time;  fdfn[time]:=v;  if hs[fa[v]]=v then head[v]:=head[fa[v]]  else head[v]:=v;  p:=con[v];  if hs[v]>0 then dfs2(hs[v]);  while p<>nil do  begin    if (p^.t<>fa[v])and(p^.t<>hs[v]) then dfs2(p^.t);    p:=p^.next;  end;end;procedure build(var x:xtree;sum,max,l,r:longint);begin  new(x);  x^.l:=l;  x^.r:=r;  x^.max:=max;  x^.sum:=sum;  x^.ls:=nil;  x^.rs:=nil;end;procedure updata(var x:xtree);begin  x^.sum:=0;  x^.max:=0;  if x^.ls<>nil then begin x^.sum:=x^.ls^.sum; x^.max:=x^.ls^.max; end;  if x^.rs<>nil then begin x^.sum:=x^.sum+x^.rs^.sum; x^.max:=maxx(x^.max,x^.rs^.max) ; end;end;procedure change(var x:xtree;v,nw,l,r:longint);var  mid:longint;begin  if x=nil then build(x,0,0,l,r);  if l=r then begin x^.max:=nw; x^.sum:=nw; exit; end;  mid:=(l+r) div 2;  if (v>=l)and(v<=mid) then change(x^.ls,v,nw,l,mid)  else change(x^.rs,v,nw,mid+1,r);  updata(x);end;procedure dele(var x:xtree;v,nw,l,r:longint);var  mid:longint;begin  if l=r then begin  x:=nil; exit; end;  mid:=(l+r) div 2;  if (v>=l)and(v<=mid) then  dele(x^.ls,v,nw,l,mid)  else dele(x^.rs,v,nw,mid+1,r);  updata(x);  if x^.sum=0 then begin  x:=nil; exit; end;end;function qsum(x:xtree;l,r:longint):longint;var  mid:longint;begin  if x=nil then exit(0);  if (l=x^.l)and(r=x^.r) then exit(x^.sum);  mid:=(x^.l+x^.r)div 2;  if r<=mid then exit(qsum(x^.ls,l,r));  if l>mid  then exit(qsum(x^.rs,l,r));  exit(qsum(x^.ls,l,mid)+qsum(x^.rs,mid+1,r));end;function qmax(x:xtree;l,r:longint):longint;var  mid:longint;begin  if x=nil then exit(0);  if (l=x^.l)and(r=x^.r) then exit(x^.max);  mid:=(x^.l+x^.r)div 2;  if r<=mid then exit(qmax(x^.ls,l,r));  if l>mid  then exit(qmax(x^.rs,l,r));  exit(maxx(qmax(x^.ls,l,mid),qmax(x^.rs,mid+1,r)));end;begin  readln(n,q);  for i:=1 to n do    readln(w[i],c[i]);  for i:=1 to n-1 do  begin    readln(u,v);    ins(u,v);    ins(v,u);  end;  dfs1(1);  dfs2(1);  for i:=1 to n do    change(xtr[c[i]],dfn[i],w[i],1,n);  for i:=1 to q do  begin    {for j:=1 to 3 do    begin      outp(xtr[j]);      writeln;    end; }    ans:=0;    read(c1);read(c1); readln(x,y);    ck:=c[x];    case c1 of      'C':begin dele(xtr[c[x]],dfn[x],w[x],1,n); c[x]:=y; change(xtr[y],dfn[x],w[x],1,n) end;      'W':begin w[x]:=y; change(xtr[c[x]],dfn[x],y,1,n) end;      'S':      begin        while head[x]<>head[y] do        begin          if deep[head[x]]>deep[head[y]] then          begin            ans:=ans+qsum(xtr[ck],dfn[head[x]],dfn[x]);            x:=fa[head[x]];          end          else          begin            ans:=ans+qsum(xtr[ck],dfn[head[y]],dfn[y]);            y:=fa[head[y]];          end;        end;        if deep[x]<=deep[y] then ans:=ans+qsum(xtr[ck],dfn[x],dfn[y])        else ans:=ans+qsum(xtr[ck],dfn[y],dfn[x]);        writeln(ans);      end;      'M':      begin        while head[x]<>head[y] do        begin          if deep[head[x]]>deep[head[y]] then          begin            ans:=maxx(ans,qmax(xtr[ck],dfn[head[x]],dfn[x]));            x:=fa[head[x]];          end          else          begin            ans:=maxx(ans,qmax(xtr[ck],dfn[head[y]],dfn[y]));            y:=fa[head[y]];          end;        end;        if deep[x]<=deep[y] then ans:=maxx(ans,qmax(xtr[ck],dfn[x],dfn[y]))        else ans:=maxx(ans,qmax(xtr[ck],dfn[y],dfn[x]));        writeln(ans);      end;    end;  end;end. 
0 0
原创粉丝点击