这个题我愣是交了好几遍没有过......

后来@_皎月半洒花dalao告诉我说要^儿子节点的tag,然后就明白了......

行吧,先上题面:

题目描述

现有N(2 ≤ N ≤ 100000)盏灯排成一排,从左到右依次编号为:1,2,......,N。然后依次执行M(1 ≤ M ≤ 100000)项操作,操作分为两种:第一种操作指定一个区间[a, b],然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开),第二种操作是指定一个区间[a, b],要求你输出这个区间内有多少盏灯是打开的。灯在初始时都是关着的。

输入输出格式

输入格式:

第一行有两个整数N和M,分别表示灯的数目和操作的数目。接下来有M行,每行有三个整数,依次为:c, a, b。其中c表示操作的种类,当c的值为0时,表示是第一种操作。当c的值为1时表示是第二种操作。a和b则分别表示了操作区间的左右边界(1 ≤ a ≤ b ≤ N)。

输出格式:

每当遇到第二种操作时,输出一行,包含一个整数:此时在查询的区间中打开的灯的数目。

这个题比较水有好处的一点是有很多题都和这个题基本一样。

然后我们看到这个题让我们统计一个线段内的某一种和和修改区间:

线段树啊!

然后我就把校门外的树的代码扒过来了......

评测记录

后果:听取WA声一片。

为啥呢?

因为儿子节点有可能比父亲节点提前改过了。

所以我们只能取反,把原先的状态反过来。

然后就成了提交记录

#include <iostream>
#include <cstdio> using namespace std;
const int maxn=100001;
struct tree{
int l,r,flash,dark;
bool tag;
}segment[maxn<<2];
int n,m; inline void update(int rt);
inline void pushdown(int rt);
inline void build_tree(int rt,int l,int r);
inline int query(int rt,int l,int r);
inline void modify(int rt,int l,int r); int main()
{
cin>>n>>m;
build_tree(1,1,n);
while (m--)
{
char flag;
int l,r;
cin>>flag>>l>>r;
if (flag=='0')modify(1,l,r);
else cout<<query(1,l,r)<<'\n';
}
return 0;
} inline void update(int rt)
{
int lson=rt<<1,rson=lson+1;
segment[rt].flash=segment[lson].flash+segment[rson].flash;
segment[rt].dark=segment[lson].dark+segment[rson].dark;
}
inline void pushdown(int rt)
{
int lson=rt<<1,rson=lson+1;
segment[lson].tag^=1;
segment[rson].tag^=1;
swap(segment[lson].dark,segment[lson].flash);
swap(segment[rson].dark,segment[rson].flash);
segment[rt].tag^=1;
}
inline void build_tree(int rt,int l,int r)
{
segment[rt].l=l,segment[rt].r=r;
if (l==r)
{
segment[rt].flash=0;
segment[rt].dark=1;
segment[rt].tag=false;
return;
}
int mid=(r+l)>>1,lson=rt<<1,rson=lson+1;
build_tree(lson,l,mid);
build_tree(rson,mid+1,r);
update(rt);
}
inline void modify(int rt,int l,int r)
{
if (segment[rt].l<=l&&segment[rt].r>=r)
{
if (segment[rt].l==l&&segment[rt].r==r)
{
segment[rt].tag^=1;
swap(segment[rt].flash,segment[rt].dark);
return;
}
if (segment[rt].tag)pushdown(rt);
int mid=(segment[rt].l+segment[rt].r)>>1,lson=rt<<1,rson=lson+1;
if (r<=mid)modify(lson,l,r);
else if (l>mid)modify(rson,l,r);
else
{
modify(lson,l,mid);
modify(rson,mid+1,r);
}
update(rt);
}
return ;
}
inline int query(int rt,int l,int r)
{
if (segment[rt].l<=l&&segment[rt].r>=r)
{
if (segment[rt].l==l&&segment[rt].r==r)
{
return segment[rt].flash;
}
if (segment[rt].tag)pushdown(rt);
int mid=(segment[rt].l+segment[rt].r)>>1,lson=rt<<1,rson=lson+1;
if (r<=mid)return query(lson,l,r);
else if (l>=mid+1)return query(rson,l,r);
else return query(lson,l,mid)+query(rson,mid+1,r);
}
return 0;
}

行吧......

题解 P3870 【[TJOI2009]开关】的更多相关文章

  1. 洛谷 P3870 [TJOI2009]开关 题解

    原题链接 前置知识: 线段树的单点.区间的修改与查询. 一看,我们需要维护两个操作: 区间取反: 区间求和. (因为区间 \(1\) 的个数,就是区间的和) 典型的 线段树 . 如果你只会线段树的 区 ...

  2. 洛谷 P3870 [TJOI2009]开关

    题意简述 有n盏灯,默认为关,有两个操作: 1.改变l~r的灯的状态(把开着的灯关上,关着的灯打开) 2.查询l~r开着的灯的数量 题解思路 维护一个线段树,支持区间修改,区间查询 懒标记每次^1 代 ...

  3. P3870 [TJOI2009]开关

    思路 重题 代码 #include <iostream> #include <vector> #include <cstdio> #include <cstr ...

  4. 洛谷P3870 [TJOI2009]开关

    题目描述 现有\(N(2 ≤ N ≤ 100000)\)盏灯排成一排,从左到右依次编号为:\(1,2,......,N\).然后依次执行\(M(1 ≤ M ≤ 100000)\)项操作,操作分为两种: ...

  5. 洛谷P3870 [TJOI2009] 开关 (线段树)

    简单的省选题...... 打异或标记即可. 1 #include<bits/stdc++.h> 2 const int N=2e5+10; 3 using namespace std; 4 ...

  6. 题解 P3870 【[TJOI2009]开关】/基础分块学习小结

    直接进入正题: 分块: 分块分块,就是把一个长串东西,分为许多块,这样,我们就可以在操作一个区间的时候,对于在区间里面完整的块,直接操作块,不完整的直接操作即可,因为不完整,再加上一个块本身就不大,复 ...

  7. 洛谷 3870 [TJOI2009]开关

    [题解] 线段树基础题.对于每个修改操作把相应区间的sum改为区间长度-sum即可. #include<cstdio> #include<algorithm> #include ...

  8. [TJOI2009]开关 (线段树)

    题目描述 现有N(2 ≤ N ≤ 100000)盏灯排成一排,从左到右依次编号为:1,2,......,N.然后依次执行M(1 ≤ M ≤ 100000)项操作,操作分为两种:第一种操作指定一个区间[ ...

  9. Luogu3870 [TJOI2009]开关 (分块)

    线段树做法很简单,但分块好啊 #include <iostream> #include <cstdio> #include <cstring> #include & ...

随机推荐

  1. SSD固态硬盘的GC与Trim

    操作系统:其实并没有删除数据: 事实上,它只是在硬盘前的索引区里标记这块文件占用的区域为无效的, 所以等该区域被擦除后,下次数据将要再次写入的时候,可以写入这块被标记的区域. 这也就是为啥那 些所谓的 ...

  2. docker-compose 部署 EFK

    信息: Docker版本($ docker --version):Docker版本18.06.1-ce,版本e68fc7a 系统信息($ cat /etc/centos-release):CentOS ...

  3. 经典的性能优化最佳实践 web性能权威指南 读书笔记

    web性能权威指南 page 203 经典的性能优化最佳实践 无论什么网络,也不管所用网络协议是什么版本,所有应用都应该致力于消除或减 少不必要的网络延迟,将需要传输的数据压缩至最少.这两条标准是经典 ...

  4. JavaScript-强制类型转换

    因为没有学过其他编程语言,因此作为我的第一门编程“母语”我在这就不举其他编程语言的例子了,JavaScript这个动态类型脚本语言的变量号称是没有类型的,那么我们怎么转换他的变量呢?而且还要强行转换. ...

  5. Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之创建线程执行器

    Netty源码分析第二章: NioEventLoop 概述: 通过上一章的学习, 我们了解了Server启动的大致流程, 有很多组件与模块并没有细讲, 从这个章开始, 我们开始详细剖析netty的各个 ...

  6. Streamr助你掌控自己的数据(2)——三种整合数据至Streamr的典型场景

    博客说明 所有刊发内容均可转载但是需要注明出处. 三种整合数据至Streamr的典型场景 本系列文档主要介绍怎么通过Streamr管理自己的DATA,整个系列包括三篇教程文档,分别是:教你5分钟上传数 ...

  7. word2vec入门理解的博客整理

    深度学习word2vec笔记之基础篇 https://blog.csdn.net/mytestmy/article/details/26961315 深度学习word2vec笔记之算法篇 https: ...

  8. css 剩余宽度完全填充

    从网上转的. <html> <head> <meta http-equiv="Content-Type" content="text/htm ...

  9. Excel VBA宏 链接服务器 上传和下载数据

    首先说明以下. 第一: 下面的 “ _" 也就是 空格下划线 在VBA中表示换行的意思:& 表示链接连个字符串的操作,注意 & 的前后是否需要空格 第二: 如果链接服务器,服 ...

  10. Vue 入门之数据绑定

    什么是双向绑定? Vue 框架很核心的功能就是双向的数据绑定. 双向是指:HTML 标签数据 绑定到 Vue 对象,另外反方向数据也是绑定的.通俗点说就是,Vue 对象的改变会直接影响到 HTML 的 ...