二维线段树+标记永久化 poj2155

省选之后好久没做题了呀。。。

二维线段树其实就是把线段树的节点变为一棵线段树,以坐标轴为例,先查询x轴范围,再在表示x轴节点内查询y轴节点,时间复杂度维持在o(logn*logn)内。

2155这道题是在坐标轴中,动态修改矩阵值(xor),询问某一a(x,y)是1或0。

由于是二维,想到了二维线段树,由于涉及区间修改,单点查询,用到了标记永久化。

二维线段树上面已经介绍过了,标记永久化则是在zkw线段树中非常好用的手段,将信息存在尽可能靠近根部位置(zkw的自底向上可以很快找到这一位置)不再下放,询问的时候只需根据叶子到根的路径上的每一个标记进行修改就可以了。

关于zkw线段树可以看论文,或我之前写的几篇文章。具体实现参见程序。

var b:array[1..2048,1..2048]of integer;
    n,m,t,m1,ans:longint;
procedure operate2(k,y1,y2:longint);
var l,r:longint;
begin
 l:=y1+m1-1;r:=y2+m1+1;
 while not(l xor r=1) do begin
  if l and 1=0 then b[k,l+1]:=b[k,l+1] xor 1;
  if r and 1=1 then b[k,r-1]:=b[k,r-1] xor 1;
  l:=l>>1;r:=r>>1
 end
end;
procedure operate(x1,y1,x2,y2:longint);
var l,r:longint;
begin
 l:=x1+m1-1;r:=x2+m1+1;
 while not(l xor r=1) do begin
  if l and 1=0 then operate2(l+1,y1,y2);
  if r and 1=1 then operate2(r-1,y1,y2);
  l:=l>>1;r:=r>>1
 end
end;
procedure ask2(k,y1:longint);
begin
 y1:=y1+m1;
 while y1<>0 do begin
  ans:=ans xor b[k,y1];
  y1:=y1>>1
 end
end;
procedure ask(x1,y1:longint);
begin
 x1:=x1+m1;
 while x1<>0 do begin
  ask2(x1,y1);
  x1:=x1>>1;
 end
end;
procedure origin;
begin
 fillchar(b,sizeof(b),0);
 m1:=1;
 while m1<=n+2 do m1:=m1<<1;m1:=m1-1
end;
procedure init;
var i,x1,y1,x2,y2:longint;
    q,q1:char;
begin
 readln(n,m);
 origin;
 for i:=1 to m do begin
  read(q,q1);
  if q='C' then begin
   readln(x1,y1,x2,y2);
   operate(x1,y1,x2,y2)
  end
  else begin
   readln(x1,y1);ans:=0;
   ask(x1,y1);
   writeln(ans)
  end
 end;
 writeln;
end;
begin
//assign(input,'2155.in');reset(input);
 readln(t);
 for t:=1 to t do init;
//close(input)
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值