【BZOJ1103】大都市meg(DFS序,树状数组)
题意:有一颗树,1号点为根,保证编号小的点深度较小,初始状态每条边都没有被标记,要求实现两个操作在线:
A:将连接x,y的边标记
W:查询从1到x的路径上有多少条边未被标记
n<=2*10^5
思路:本题的特殊性质:
1.一次只标记一条边且没有重边
2.直接求1到x的路径,不用LCA
记录i点在DFS序中第一次与最后一次出现的时间b[i]与c[i]
可以发现若(x,y)(x<y)边被标记只对区间(b[y],c[y])有1的贡献
等价于前缀和s[b[y]]++ s[c[y]+1]--
至于s[c[y]+1]--还是s[c[y]]--并不重要,因为询问的肯定是s[a[i]]之类的,而DFS序上不会出现重复
单点修改,树状数组前缀和实现
1 var head,vet,next,a,b,c,t,flag:array[1..1000000]of longint; 2 n,m,tot,i,x,y,time,j,k:longint; 3 ch:string; 4 5 procedure add(a,b:longint); 6 begin 7 inc(tot); 8 next[tot]:=head[a]; 9 vet[tot]:=b; 10 head[a]:=tot; 11 end; 12 13 procedure dfs(u:longint); 14 var e,v:longint; 15 begin 16 flag[u]:=1; inc(time); a[time]:=u; b[u]:=time; 17 e:=head[u]; 18 while e<>0 do 19 begin 20 v:=vet[e]; 21 if flag[v]=0 then dfs(v); 22 e:=next[e]; 23 end; 24 inc(time); a[time]:=u; c[u]:=time; 25 end; 26 27 function lowbit(x:longint):longint; 28 begin 29 exit(x and (-x)); 30 end; 31 32 function sum(x:longint):longint; 33 begin 34 sum:=0; 35 while x>0 do 36 begin 37 sum:=sum+t[x]; 38 x:=x-lowbit(x); 39 end; 40 end; 41 42 procedure update(x,y:longint); 43 begin 44 while x<=n<<1 do 45 begin 46 t[x]:=t[x]+y; 47 x:=x+lowbit(x); 48 end; 49 end; 50 51 begin 52 assign(input,'bzoj1103.in'); reset(input); 53 assign(output,'bzoj1103.out'); rewrite(output); 54 readln(n); 55 for i:=1 to n-1 do 56 begin 57 readln(x,y); 58 add(x,y); 59 add(y,x); 60 end; 61 dfs(1); 62 for i:=1 to n do 63 begin 64 update(b[i],1); 65 update(c[i],-1); 66 end; 67 readln(m); 68 for i:=1 to n+m-1 do 69 begin 70 readln(ch); x:=0; y:=0; 71 if ch[1]='W' then 72 begin 73 for j:=3 to length(ch) do x:=x*10+ord(ch[j])-ord('0'); 74 writeln(sum(b[x])-1); 75 end; 76 if ch[1]='A' then 77 begin 78 for j:=3 to length(ch) do 79 begin 80 if ch[j]=' ' then break; 81 x:=x*10+ord(ch[j])-ord('0'); 82 end; 83 k:=j; 84 for j:=k+1 to length(ch) do y:=y*10+ord(ch[j])-ord('0'); 85 update(b[y],-1); 86 update(c[y],1); 87 end; 88 end; 89 close(input); 90 close(output); 91 end.
null