线段树:
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.