01线段树¶
例题 #1 [TJOI2009] 开关¶
题目描述
现有 \(n\) 盏灯排成一排,从左到右依次编号为:\(1\),\(2\),……,\(n\)。然后依次执行 \(m\) 项操作。
操作分为两种:
-
指定一个区间 \([a,b]\),然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开);
-
指定一个区间 \([a,b]\),要求你输出这个区间内有多少盏灯是打开的。
灯在初始时都是关着的。
输入格式
第一行有两个整数 \(n\) 和 \(m\),分别表示灯的数目和操作的数目。
接下来有 \(m\) 行,每行有三个整数,依次为:\(c\)、\(a\)、\(b\)。其中 \(c\) 表示操作的种类。
-
当 \(c\) 的值为 \(0\) 时,表示是第一种操作。
-
当 \(c\) 的值为 \(1\) 时,表示是第二种操作。
\(a\) 和 \(b\) 则分别表示了操作区间的左右边界。
输出格式
每当遇到第二种操作时,输出一行,包含一个整数,表示此时在查询的区间中打开的灯的数目。
对于全部的测试点,保证 \(2\le n\le 10^5\),\(1\le m\le 10^5\),\(1\le a,b\le n\),\(c\in\{0,1\}\)。
线段树维护01翻转tag。
/*
Edit by Ntsc.
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define pii pair<int, int>
#define pf first
#define ps second
#define rd read()
#define ot write
#define nl putchar('\n')
inline int rd{
int xx=0,ff=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') ff=-1;ch=getchar();}
while(ch>='0'&&ch<='9') xx=xx*10+(ch-'0'),ch=getchar();
return xx*ff;
}
inline void write(int out){
if(out<0) putchar('-'),out=-out;
if(out>9) write(out/10);
putchar(out%10+'0');
}
const int N=4e5+5;
const int M=5e4+5;
const int INF=2e18+5;
const int MOD=1e9+7;
const int BASE=17737;
bool f1;
int m;
int n,tr[N],tag[N];
bool f2;
void pushup(int x){
tr[x]=tr[x<<1]+tr[x<<1|1];
}
void addtag(int x,int l,int r){
tr[x]=r-l+1-tr[x];
tag[x]^=1;
}
void pushdown(int x,int l,int r){
int mid=l+r>>1;
if(!tag[x])return ;
addtag(x<<1,l,mid);
addtag(x<<1|1,mid+1,r);
tag[x]=0;
}
void change(int x,int l,int r,int pl,int pr){
if(l>=pl&&r<=pr){
addtag(x,l,r);
// cerr<<"ck";
return ;
}
pushdown(x,l,r);
int mid=l+r>>1;
if(pl<=mid)change(x<<1,l,mid,pl,pr);
if(pr>mid)change(x<<1|1,mid+1,r,pl,pr);
pushup(x);
}
int query(int x,int l,int r,int pl,int pr,int tg){
if(l>=pl&&r<=pr){
return tr[x];
}
pushdown(x,l,r);
int res=0;
int mid=l+r>>1;
if(pl<=mid)res+=query(x<<1,l,mid,pl,pr,tg^tag[x]);
if(pr>mid)res+=query(x<<1|1,mid+1,r,pl,pr,tg^tag[x]);
return res;
}
signed main(){
n=rd,m=rd;
for(int i=1;i<=m;i++){
int op=rd;
int a=rd,b=rd;
if(op){
cout<<query(1,1,n,a,b,0)<<endl;
}else{
change(1,1,n,a,b);
}
}
return 0;
}
/*
*/