线段树:

1、【codevs1690】开关灯

这道题是一道线段树裸题,可以开个标记记录当前节点被修改的次数,然后仿照区间修改区间查询来做就行了。

代码:

uses math;
type hh=record
  l,r,x,sum:longint;
end;
var a:array[0..400010]of hh;
  n,m,i,x,l,r:longint;
function calc(now:longint):longint;
begin
  exit(a[now].r-a[now].l+1);
end;
procedure build(now,l,r:longint);
begin
  a[now].l:=l; a[now].r:=r; a[now].x:=0; a[now].sum:=0;
  if l<>r then begin
    build(now<<1,l,(l+r)>>1); build(now<<1 or 1,(l+r)>>1+1,r);
  end;
end;
procedure change(now,l,r:longint);
begin
  if(l<=a[now].l)and(a[now].r<=r)then begin
    a[now].x:=a[now].x xor 1; a[now].sum:=calc(now)-a[now].sum;
  end
  else begin
    if l<a[now<<1 or 1].l then change(now<<1,l,r);
    if a[now<<1].r<r then change(now<<1 or 1,l,r);
    a[now].sum:=a[now<<1].sum+a[now<<1 or 1].sum;
    if a[now].x=1 then a[now].sum:=calc(now)-a[now].sum;
  end;
end;
function query(now,l,r:longint):longint;
var ret:longint;
begin                                                                     
  if(l=a[now].l)and(a[now].r=r)then exit(a[now].sum)
  else begin
    ret:=0;
    if l<a[now<<1 or 1].l then ret:=ret+query(now<<1,l,min(r,a[now<<1].r));
    if a[now<<1].r<r then ret:=ret+query(now<<1 or 1,max(l,a[now<<1 or 1].l),r);
    if a[now].x=0 then exit(ret)
    else exit(r-l+1-ret);
  end;
end;
begin
  read(n,m);
  build(1,1,n);
  for i:=1 to m do begin
    read(x,l,r);
    if x=0 then change(1,l,r)
    else writeln(query(1,l,r));
  end;
end.
View Code

相关文章:

  • 2021-08-17
  • 2021-09-11
  • 2021-07-13
  • 2022-12-23
  • 2021-07-24
  • 2021-07-27
  • 2021-05-23
  • 2021-09-26
猜你喜欢
  • 2022-12-23
  • 2021-09-06
  • 2021-06-29
  • 2021-10-09
  • 2022-12-23
  • 2021-09-10
  • 2022-12-23
相关资源
相似解决方案