zkw線段樹的標記上傳好像只能做區間修改的rmq,但標記下放應用面就與樸素線段樹差不多了,但是漂亮很多。
在進行修改或詢問時,我們先將當前區間的標記全部下放,從左右開區間端點從頂向下跑一邊下放就是,同時,對於修改後,再從左右區間把祖先更新,zkw的非遞迴性質發揮的淋漓盡致。其實很好編,下面兩道題都是1a、
好吧,我又重溫了zkw的部落格,這種方法不太純正,但是,暫時還不理解那種標記永久化,所以還是先用這種方法。
rqnoj 中國結
題意:子樹取反,子樹詢問1的個數。
轉成括號序列線段樹維護,線段樹記1的數目,取反標記域。
跑得不是很快,主要是rqnoj上pascal每個點最快速度都要比c慢幾十ms
var sum,t:array[1..524288]of longint;
n,m,ans,m1,ss,len,high:longint;
l,r,tail:array[1..200000]of longint;
next,sora:array[1..500000]of longint;
procedure inf;
begin
assign(input,'chinese.in');reset(input);
assign(output,'chinese.out');rewrite(output)
end;
procedure ouf;
begin
close(input);close(output)
end;
procedure pushdown(x:longint);
var p,i,ne:longint;
begin
p:=m1;
for i:=high downto 1 do begin
p:=p>>1;
if t[x>>i]<>0 then begin
ne:=x>>i;
sum[ne<<1]:=p-sum[ne<<1]; t[ne<<1]:=t[ne<<1] xor 1;
sum[ne<<1+1]:=p-sum[ne<<1+1];t[ne<<1+1]:=t[ne<<1+1] xor 1;
t[ne]:=0
endend
end;
procedure updata(x:longint);
begin
while x<>0 do begin
sum[x]:=sum[x<<1]+sum[x<<1+1];
x:=x>>1
endend;
procedure modify(l,r:longint);
var ll,rr,p:longint;
begin
l:=l+m1-1;r:=r+m1+1;
ll:=l>>1;rr:=r>>1;
p:=1;
pushdown(l);pushdown(r);
while not(l xor r=1) do begin
if l and 1=0 then begin sum[l+1]:=p-sum[l+1];t[l+1]:=t[l+1] xor 1 end;
if r and 1=1 then begin sum[r-1]:=p-sum[r-1];t[r-1]:=t[r-1] xor 1 end;
l:=l>>1;r:=r>>1;p:=p<<1
end;
updata(ll);updata(rr)
end;
function ask(l,r:longint ): longint;
begin
l:=l+m1-1;r:=r+m1+1;ask:=0;
pushdown(l);pushdown(r);
while not(l xor r=1) do begin
if l and 1=0 then ask:=ask+sum[l+1];
if r and 1=1 then ask:=ask+sum[r-1];
l:=l>>1;r:=r>>1
endend;
procedure origin;
var i:longint;
begin
m1:=1;high:=0; //high
while m1<=n<<1+2 do begin
m1:=m1<<1;inc(high)
end;
for i:=1 to n do tail[i]:=i;ss:=n
end;
procedure link(x,y:longint);
begin
inc(ss);next[tail[x]]:=ss;tail[x]:=ss;sora[ss]:=y;
inc(ss);next[tail[y]]:=ss;tail[y]:=ss;sora[ss]:=x
end;
procedure dfs(x,y:longint);
var i,ne:longint;
begin
inc(len);l[x]:=len;
i:=x;
while next[i]<>0 do begin
i:=next[i];ne:=sora[i];
if ne<>y then dfs(ne,x)
end;
inc(len);r[x]:=len
end;
procedure init;
var i,x,y:longint;
ch:char;
begin
readln(n);
origin;
for i:=1 to n-1 do begin
readln(x,y);
link(x,y)
end;
len:=0;
dfs(1,0);
readln(m);
for i:=1 to m do begin
readln(ch,x);
if ch='c' then begin
modify(l[x],r[x])
endelse begin
ans:=ask(l[x],r[x]);
writeln(ans>>1)
endend;
end;
begin
inf;
init;
oufend.
poj 2777
題意:區間染色,統計區間顏色數目。
練手題,速度是pascal第一,總排名第一版,空間也不錯。
var c,t:array[1..262144]of longint;
ans,n,p,o,high,m1:longint;
procedure pushdown(x:longint);
var i,ne:longint;
begin
for i:=high downto 1 do
if t[x>>i]<>0 then begin
ne:=x>>i;
c[ne<<1]:=t[ne];c[ne<<1+1]:=t[ne];
t[ne<<1]:=t[ne];t[ne<<1+1]:=t[ne];
t[ne]:=0
endend;
procedure updata(x:longint);
begin
while x<>0 do begin
c[x]:=c[x<<1] or c[x<<1+1];
x:=x>>1
end;
end;
procedure modify(l,r,color:longint);
var ll,rr,e:longint;
begin
if l>r then begin
e:=l;l:=r;r:=e
end;
l:=l+m1-1;r:=r+m1+1;color:=1<<(color-1);
ll:=l>>1;rr:=r>>1;
pushdown(l);pushdown(r);
while not(l xor r=1) do begin
if l and 1=0 then begin
c[l+1]:=color;
t[l+1]:=c[l+1]
end;
if r and 1=1 then begin
c[r-1]:=color;
t[r-1]:=c[r-1]
end;
l:=l>>1;r:=r>>1
end;
updata(ll);updata(rr)
end;
function ask(l,r:longint ): longint;
var e,k:longint;
begin
if l>r then begin
e:=l;l:=r;r:=e
end;
l:=l+m1-1;r:=r+m1+1;
ask:=0;
pushdown(l);pushdown(r);
while not(l xor r=1) do begin
if l and 1=0 then ask:=ask or c[l+1];
if r and 1=1 then ask:=ask or c[r-1];
l:=l>>1;r:=r>>1
end;
k:=0;
while ask<>0 do begin
k:=k+ask and 1;
ask:=ask>>1
end;
exit(k)
end;
procedure origin;
begin
m1:=1;high:=0;
while m1
線段樹和zkw線段樹
好啦,我們就開始說說線段樹吧 線段樹是個支援區間操作和查詢的東東,平時的話還是蠻實用的 下面以最基本的區間加以及查詢區間和為例 線段樹顧名思義就是棵樹嘛,葉子節點是每個基本點,它們所對應的父親就是它們的和,具體如下圖 但是對於這樣的線段樹來說,操作所需的時間是遠達不到我們的要求的 會被t 因為我們會...
zkw線段樹小結
zkw zkwzk w線段樹作為迴圈式線段樹具有較小的常數.其實樹狀陣列本質上就是線段樹 下標為 1,n 1,n 1,n 預處理乙個2 k n2 k n 2k n.然後總空間為2k 12 2k 1 2 k 1 4n 2 4n 2k 1 4n 後面令k 2 kk 2 k k 2k 那麼乙個葉子x xx...
鏈結 zkw線段樹
資料結構 走近zkw線段樹 一 資料結構 走近zkw線段樹 二 線段樹的擴充套件之 zkw線段樹 include define lc x x 1 define rc x x 1 1 using namespace std const int maxn 100005 int max int a,int...