2017.6.4 入门组 NO.6——树

来源:互联网 发布:什么是移动云计算 编辑:程序博客网 时间:2024/05/22 12:35

这里写图片描述
这里写图片描述


80%:做不出100%,先来个80分水法     首先将x,y之间有边的记录两个,存在a数组里,一个是x,y,另一个是y,x     然后将这个a数组排序,将a[i,1]按升序排序。     Then 就可以求出每一个点与多少个点有边,求出每一个点的"子点"的区间,用l和r数组存     再用dfs求出以1作根,每一个点的father是谁     预处理Over     如果为1,新建一个数组k来存它们的变化;     如果为2,就从这个点往回推,如果为偶数次就+k[j],如果为奇数次就-k[j],j=father[j]

80%代码:

var a:array[0..200000,1..2]of longint;    father,l,r,k,d:array[0..100000]of longint;    v:array[0..100000]of boolean;    n,m,i,j,z,y,x,w:longint;procedure qsort(l,r:longint);var  i,j,mid:longint;begin  if l>=r then exit;  i:=l; j:=r; mid:=a[(l+r) div 2,1];  repeat    while a[i,1]<mid do inc(i);    while a[j,1]>mid do dec(j);    if i<=j then      begin        a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];        inc(i);dec(j);      end;  until i>j;  qsort(i,r);  qsort(l,j);end;procedure find_father(x:longint);var  i:longint;begin  v[x]:=false;  for i:=l[x] to r[x] do    if v[a[i,2]]=true then      begin        father[a[i,2]]:=x;        find_father(a[i,2]);      end;end;begin  readln(n,m);  for i:=1 to n do read(d[i]);  readln;  for i:=1 to n-1 do    begin      readln(x,y);      a[i*2-1,1]:=x;      a[i*2-1,2]:=y;      a[i*2,1]:=y;      a[i*2,2]:=x;    end;  qsort(1,(n-1)*2);  for i:=1 to (n-1)*2 do    begin      if a[i,1]<>a[i-1,1] then l[a[i,1]]:=i;      if a[i,1]<>a[i+1,1] then r[a[i,1]]:=i;    end;  fillchar(v,sizeof(v),true);  find_father(1);  for i:=1 to m do    begin      read(x);      if x=1 then        begin          readln(j,y);          k[j]:=k[j]+y;        end;      if x=2 then        begin          readln(w);          j:=w;y:=0;z:=d[w];          while j<>0 do            begin              y:=1-y;              if y=0 then z:=z-k[j] else z:=z+k[j];              j:=father[j];            end;          writeln(z);        end;    end;end.
原创粉丝点击