洛谷 P5057 [CQOI2006]简单题 题解
P5057 [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
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 ≤ 10^3\),$ 1 ≤ m ≤ 10^4$; 对于 100% 的数据,\(1 ≤ n ≤ 10^5\), \(1 ≤ m ≤ 5 × 10^5\),保证 L ≤ R。
【树状数组】
【思路】
树状数组
【题目大意】
区间反转和单点询问
【题目分析】
区间反转我首先想到了是线段树
用lazy标记某个区间反转过几次
但是我是抱着练习树状数组的目的
来做的这道题
所以必须用树状数组做!!!
不过树状数组该怎么办呢?
难不成枚举每一个点然后修改?
不对
这个时候情不自禁想到了那个优美的东西
差分
类似树状数组模板2的方法
差分一下下就可以很轻松标记翻转次数了
【核心思路】
树状数组维护差分数组
差分数组修改区间
只需要在区间左端点加上修改的值
在右端点之后减去修改的值就好了
求某个位置上的值
就是这个位置之前(包括这个位置)的和
也符合树状数组里面的sum
就不需要做差了
最后按照%2来输出就好了
因为翻转两次之后会回到原来的情况
【思路】
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int Max = 100006;
int a[Max];
int n,m;
int read()
{
	int sum = 0,fg = 1;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-')fg = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		sum = sum * 10 + c - '0';
		c = getchar();
	}
	return sum * fg;
}
int lowbit(int x)
{
	return x & -x;
}
void add(int x,int y)
{
	while(x <= n)
	{
		a[x] += y;
		x += lowbit(x);
	}
}
int sum(int x)
{
	int ans = 0;
	while(x > 0)
	{
		ans += a[x];
		x -= lowbit(x);
	}
	return ans;
}
signed main()
{
	n = read(),m = read();
	for(register int i = 1;i <= m;++ i)
	{
		int t = read();
		if(t == 1)
		{
			int l = read(),r = read();
			add(l,1);
			add(r + 1,-1);
		}
		else
		{
			int qwq = read();
			cout << sum(qwq) % 2 << endl;
		}
	}
	return 0;
}
【线段树】
【思路】
线段树
首先感谢@大魔鬼灿灿 巨佬帮我滑鼠标
用树状数组做过了,但是还是可以用线段树做的
所以也拿线段树来做回顾一下线段树,
然后没想到调试了两个小时
【核心思路】
sum记录这个点被修改的次数
因为是区间修改和单点查询
所以线段树中只要不是叶子节点的sum就不需要求了
只用来lazy标记就可以了
然后该下放到叶子节点的时候就下发好了
最后输出记录的修改次数%2
【注意事项】
不管不是叶子节点的sum没问题
但是有的修改的时候却是单点修改
所以该sum++还是得sum++的
把全部节点的sum都当叶子节点的来处理
加上修改的次数
也就是lazy值就好了
【完整代码】
#include<iostream>
#include<cstdio>
#define lson (k << 1)
#define rson (k << 1 | 1)
using namespace std;
int read()
{
	int sum = 0,fg = 1;
	char c = getchar();
	while(c < '0' || c > '9'){if(c == '-')fg = -1;c = getchar();}
	while(c >= '0' && c <= '9'){sum = sum * 10 + c - '0';c = getchar();}
	return sum * fg;
}
const int Max = 100004;
struct node
{
	int l,r;
	int lazy;
	int sum;
}a[Max << 2];
int n,m;
int opx,opl,opr;
void build(int k,int l,int r)
{
	a[k].l = l;a[k].r = r;
	if(l == r)
		return;
	int mid = (l + r) >> 1;
	build(lson,l,mid);
	build(rson,mid + 1,r);
	return;
}
void down(int k)
{
	if(a[k].lazy)
	{
		a[lson].sum += a[k].lazy;
		a[rson].sum += a[k].lazy;
		a[lson].lazy += a[k].lazy;
		a[rson].lazy += a[k].lazy;
		a[k].lazy = 0;
	}
}
void change(int k)
{
	if(opl <= a[k].l && opr >= a[k].r)
	{
		a[k].lazy ++;
        a[k].sum++;
		return;
	}
	down(k);
	int mid = (a[k].l + a[k].r) >> 1;
	if(opl <= mid)change(lson);
	if(opr > mid)change(rson);
	a[k].sum = a[lson].sum + a[rson].sum;
}
void query(int k)
{
	if(a[k].l == opx && a[k].r == opx)
	{
		cout << a[k].sum % 2 << endl;
        return;
	}
	down(k);
	int mid = (a[k].l + a[k].r) >> 1;
	if(opx <= mid) query(lson);
	if(opx > mid) query(rson);
}
int main()
{
	n = read(),m = read();
	build(1,1,n);
	for(register int i = 1;i <= m;++ i)
	{
		int qwq = read();
		if(qwq == 1)
		{
			opl = read(),opr = read();
			change(1);
		}
		else
		{
			opx = read();query(1);
		}
	}
	return 0;
}
洛谷 P5057 [CQOI2006]简单题 题解的更多相关文章
- 洛谷 P5057 [CQOI2006]简单题 (树状数组,位运算)
		题意:有一个长度为\(n\)的数组,进行\(m\)次操作,每次读入一个值\(t\),如果\(t=1\),则将区间\([l,r]\)的数字反转,若\(t=2\),则查询下标为\(i\)的值. 题解:树状 ... 
- 洛谷P5057 [CQOI2006]简单题(线段树)
		题意 题目链接 Sol 紫色的线段树板子题??... #include<iostream> #include<cstdio> #include<cmath> usi ... 
- [洛谷P5057][CQOI2006]简单题
		题目大意:有一个长度为$n$的$01$串,两个操作: $1\;l\;r:$把区间$[l,r]$翻转($0->1,1->0$) $2\;p:$求第$p$位是什么 题解:维护前缀异或和,树状数 ... 
- 洛谷 P5057 [CQOI2006]简单题(树状数组)
		嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ... 
- P5057 [CQOI2006]简单题(线段树)
		果然简单题,5分钟紫题++ 代码 #include <cstdio> #include <algorithm> #include <cstring> using n ... 
- 洛谷P1072Hankson的趣味题题解
		题目 一道十分经典的数论题,在考场上也可以用暴力的算法来解决,从而得到\(50pts\)的较为可观的分数,而如果想要AC的话,我们观察原题给的数据范围\(a,b,c,d\)(为了好表示,分别代表a1, ... 
- 【洛谷P4148】简单题(kd-tree)
		传送门 题意: 给出一个\(n*n\)的棋盘,现在有两种操作:一种是某个格子里的数字加上\(A\),另一种是询问矩阵和. 空间限制:\(20MB\),强制在线. 思路: 直接\(kd-tree\)来搞 ... 
- P5057 [CQOI2006]简单题 前缀异或差分/树状数组
		好思路,好思路... 思路:前缀异或差分 提交:1次 题解:区间修改,单点查询,树状数组,如思路$qwq$ #include<cstdio> #include<iostream> ... 
- P5057 [CQOI2006]简单题
		题目描述 有一个 n 个元素的数组,每个元素初始均为 0.有 m 条指令,要么让其中一段连续序列数字反转——0 变 1,1 变 0(操作 1),要么询问某个元素的值(操作 2). 例如当 n = 20 ... 
随机推荐
- HTTP之缓存是如何保持副本的新鲜的!
			缓存保持副本的新鲜 ========================摘自<HTTP权威指南>================================= 可能不是所有已缓存副本都与服 ... 
- mvn手动上传jar到本地仓库
			mvn install:install-file -Dfile=G:\elastic-project\workspace\out\artifacts\xxl_job_core_jar\xxl-job- ... 
- CentOS升级Python2.6到Python2.7并安装pip[转载]
			貌似CentOS 6.X系统默认安装的Python都是2.6版本的?平时使用以及很多的库都是要求用到2.7版本或以上,所以新系统要做的第一件事必不可少就是升级Python啦!在这里做个简单的升级操作记 ... 
- Linux 安装Mysql1.8【yum安装】
			.下载mysql的yum源 wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm2.安装yum源yum lo ... 
- java中的对象、类、包、模块、组件、容器、框架、架构的概念入门
			在Java中有那么一些概念:对象.类.包.模块.组件.容器.框架.这些概念都有一个共同的特点,就是[容纳]. 对象(Object) 在Java的世界里,对象是通过属性和方法来分别对应事务所具有的静态属 ... 
- 趣文:如何通过给MM修电脑培养感情[转]
			在修之前,向 MM 反复声明,这电脑故障是有硬件和软件之分的,如果是硬件故障,例如显卡风扇不转了,显示器连线老化,显示器分辨率超出显示器指标,等等都会导致黑屏啊,这个我不回家用专门的工具是修不好的! ... 
- 【01】Jenkins:安装配置
			写在前面的话 从我的工作经历来看,刚出来的时候的第一家公司我们上线采用的是脚本上线.就是那种开发合并完代码以后,在一个固定的时间点,我们上服务器执行更新脚本打包更新.这种方法有一个很大的问题,就是对于 ... 
- win10系统本地iis或nginx服务器部署vue.js项目
			1.前端框架一般依赖node.js,我们首先要安装node.js.请参考: http://www.cnblogs.com/wuac/p/6381819.html to:安装好node.js后npm也安 ... 
- NetCoreApi框架搭建三、JWT授权验证)
			1.首先还是粘贴大神的链接 虽然说大神的博客已经讲得很详细了,但是此处还是自己动手好点. 首先配置Startup Swagger的验证 2.新建一个项目存放tokenmodel和生成token并且存入 ... 
- 【翻译】Tusdotnet中文文档(2)事件
			tusdotnet-----一个tus文件上传协议的实现之事件 本章接上篇来继续翻译Tusdotnet的文档,按照如下结构来翻译: 事件 OnAuthorize OnFileComplete OnBe ... 
