题意:n个灯,m个操作,初始灯全是关的。两种操作:(1)0 l r 把l到r的灯全部取反(开了的关掉,关了的打开)(2) 1 l r 询问[l,r]开着的灯的个数
一眼看过去就是线段树,没毛病
对于修改,相当于每个数取异或,打标签处理一下就好了
type
rec=record
l,r,sum:longint;
flag:boolean;
end;
var
n,m,op,x,y :longint;
i :longint;
t :array[0..400010] of rec;
procedure build(x,l,r:longint);
var
mid:longint;
begin
t[x].l:=l; t[x].r:=r;
if l=r then exit;
mid:=(l+r)>>1;
build(2*x,l,mid); build(2*x+1,mid+1,r);
end;
procedure pushdown(x:longint);
begin
if t[x].flag then
begin
t[x].flag:=false;
t[2*x].flag:=not t[2*x].flag;
t[2*x].sum:=t[2*x].r-t[2*x].l+1-t[2*x].sum;
t[2*x+1].flag:=not t[2*x+1].flag;
t[2*x+1].sum:=t[2*x+1].r-t[2*x+1].l+1-t[2*x+1].sum;
end;
end;
procedure change(x,l,r:longint);
var
mid:longint;
begin
if (t[x].l=l) and (t[x].r=r) then
begin
t[x].flag:=not t[x].flag;
t[x].sum:=t[x].r-t[x].l+1-t[x].sum;
exit;
end;
pushdown(x);
mid:=(t[x].l+t[x].r)>>1;
if (r<=mid) then change(2*x,l,r) else
if (l>mid) then change(2*x+1,l,r) else
begin
change(2*x,l,mid);
change(2*x+1,mid+1,r);
end;
t[x].sum:=t[2*x].sum+t[2*x+1].sum;
end;
function get_sum(x,l,r:longint):longint;
var
mid:longint;
begin
if (t[x].l=l) and (t[x].r=r) then exit(t[x].sum);
pushdown(x);
mid:=(t[x].l+t[x].r)>>1;
if r<=mid then exit(get_sum(2*x,l,r)) else
if l>mid then exit(get_sum(2*x+1,l,r)) else
exit(get_sum(2*x,l,mid)+get_sum(2*x+1,mid+1,r));
end;
begin
read(n,m);
build(1,1,n);
for i:=1 to m do
begin
read(op,x,y);
if op=0 then change(1,x,y)
else writeln(get_sum(1,x,y));
end;
end.
——by Eirlys