P5057 [CQOI2006]简单题

120 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第25天,点击查看活动详情

[CQOI2006]简单题

题目描述

有一个 n 个元素的数组,每个元素初始均为 0。有 m 条指令,要么让其中一段连续序列数字反转——0 变 1,1 变 0(操作 1),要么询问某个元素的值(操作 2)。 例如当 n = 20 时,10 条指令如下:

输入格式

第一行包含两个整数 n, m,表示数组的长度和指令的条数; 以下 m 行,每行的第一个数 t 表示操作的种类:

若 t = 1,则接下来有两个数 L, R,表示区间 [L, R] 的每个数均反转; 若 t = 2,则接下来只有一个数 i,表示询问的下标。

输出格式

每个操作 2 输出一行(非 0 即 1),表示每次操作 2 的回答。

样例 #1

样例输入 #1

20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6

样例输出 #1

1
0
0
0
1
1

提示

对于 50% 的数据,1 ≤ n ≤ 10310^3, 1 ≤ m ≤ 10410^4; 对于 100% 的数据,1 ≤ n ≤ 10510^5, 1 ≤ m ≤ 5 × 10510^5,保证 L ≤ R。

分析

这是一道线段树的板子题,qaq,就是add函数+-操作。

代码

#include <iostream>
#define ll long long 
#include <cmath> 
using namespace std;
const int N=100010;
ll a[N],n,m;
struct tre{
	ll l,r,sum,add,mul;
}tr[4*N];
inline void pushup(ll u){
	tr[u].sum=tr[u+u].sum+tr[u+u+1].sum;
}
inline void build(ll u,ll l,ll r){
	if(l==r){
		tr[u]={l,r,a[l],0,1};
		return;
	}
	tr[u]={l,r,0,0,1};
	ll mid=l+r>>1;
	build(u+u,l,mid);
	build(u+u+1,mid+1,r);
	pushup(u);
}
inline void opp(tre &tree,ll add,ll mul){
	tree.sum=(tree.sum*mul+add*(tree.r-tree.l+1));
	tree.mul=tree.mul*mul;
	tree.add=(tree.add*mul+add);
}
inline void pushdown(ll u){
	opp(tr[u+u],tr[u].add,tr[u].mul);
	opp(tr[u+u+1],tr[u].add,tr[u].mul);
	tr[u].mul=1,tr[u].add=0; 
}
inline void modify(ll u,ll l,ll r,ll add,ll mul){
	if(tr[u].l>=l && tr[u].r<=r){
		opp(tr[u],add,mul);
		return;
	}
	pushdown(u); 
	ll mid=tr[u].l+tr[u].r>>1;
	if(r<=mid) modify(u+u,l,r,add,mul);
	else{
		if(l>mid) modify(u+u+1,l,r,add,mul);
		else{
			modify(u+u,l,mid,add,mul);
			modify(u+u+1,mid+1,r,add,mul);
		}
	}
	pushup(u);
}
ll query(ll u,ll l,ll r){
	if(tr[u].l>=l && tr[u].r<=r){
		return tr[u].sum;
	}
	pushdown(u);
	ll mid=tr[u].l+tr[u].r>>1;
	if(r<=mid) return query(u+u,l,r);
	else{
		if(l>mid) return query(u+u+1,l,r);
		else return query(u+u,l,mid)+query(u+u+1,mid+1,r); 
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) a[i]=0;
	build(1,1,n); 
	while(m--){
		ll op,l,r;
		cin>>op;
		if(op==1){
			cin>>l>>r;
			modify(1,l,r,1,-1);
		}
		else{
			cin>>l;
			cout<<(query(1,l,l))<<"\n";
		}
	}
	return 0;
}