考试的一道附加题~

一看题目描述:把区间[l,r]里每个数异或上x,求区间[l,r]里所有数的异或和,这明显的要用数据结构或RMQ吧。

恩,所以正解就是线段树啦,至于树状数组行与否,不知道~

water_lift:这不是sb题嘛?线段树板子题都不会?把加法操作改成异或操作不就好啦?

其实好像真的是这样的,将加法操作改成了乘法操作;

然后你会发现自己只得了20分的暴力分,没错!相当于没写线段树!

因为线段树区间修改需要用到一个非常重要的东西:

懒标记

为什么要用到这个,直接暴力递归不好吗?

问得好!

假设我们每进行一次加法或减法操作我们就要从根节点一直递归到它儿子再递归回来,这样做好像没什么问题,但是,太耗时!

我们不如将这个区间内的所有元素做上一个懒标记!(顾名思义,懒标记很懒嘛,查到它它才改,不查就不改!真是壮士!)

这个懒标记是干嘛滴呢?假设我们对一个区间进行了n次操作,每次操作都给这个区间加上Ai(i从1~n),不做懒标记的话我们就要递归n次,树一大节点一多直接T得飞起!

所以我们就给这个区间的元素做上懒标记,每次懒标记加上要加上的Ai的值,但是不往下递归,所以到n次操作后这个区间的元素的懒标记就是:A1+A2+A3……+An,这样我们一次递归加上懒标记就好啦。

举个例子:

sum是这个区间内的总和相对于初始化增加了多少,inc是这个区间的每个元素相对于初始化增加了多少。

然后我们可以进行第一步操作:让[2,7]的每个元素增加2

在全部的大区间[1,9]内,由于1~7都在这个区间内,所以总和相对于一开始的是增加了2*7=14,所以sum的值为14;但是[1,9]又不完全被包含在[1,7]内,所以我们不能更新inc值(看inc的定义,8和9不能+2)

因为区间[1,9]内还有元素不用+2,所以我们要继续往下找:

我们找到了区间[1,5]和区间[6,9],我们发现:区间[1,5]全部都在[1,7]内,所以区间[1,5]的inc值就可以更新为2了,sum值就是5*2=10;但是区间[6,9]还有元素不在区间[1,7]的范围内所以我们将这个区间继续往下找,同时将这个区间的sum值更新为4;

[6,9]可以分成[6,7]和[8,9],我们发现:区间[6,7]全部都在[1,7]以内,所以将区间[6,7]的inc值更新为2,sum值为2*2=4。到这步我们就发现[1,7]以内已经全部被找过了,所以我们就找完了!

接下来我们查询[1,6]的和:

还是按照原来的思路:从根节点开始找,发现[1,9]并不完全被包含在所查区间内,所以我们就去找它的儿子;

我们找到了[1,5],发现并不完全被包含在[2,6]内,所以我们继续往下找,并将inc值传给它的两个儿子;找到了[1,3]和[4,5],我们发现区间[4,5]全部被包含在内了,所以我们直接返回sum值+原区间和就好啦,sum=inc*len(区间长度)=2*2=4,但是[1,3]并不完全被包含在内,所以我们将[1,3]的inc值传给它的儿子,并继续往下找:

我们找到了[1,2]和区间[3,3](就是3),我们发现3完全被包含在所查区间内了,所以我们直接返回sum值+原区间和就好啦,sum=inc*len(区间长度)=2*1=2;但是区间[1,2]并不完全被包含在内,所以继续从它的儿子里面找,并将inc值传给儿子:

我们找到了1和2,1不在所查区间内就不管它了(不清楚懒标记inc值),我们发现2在所查区间内,所以直接返回sum值+原区间和就好啦,sum的公式就不用说了...

到这里的话,大家应该都会懒标记了QwQ~,毕竟前面讲的辣么详细。

但是还是会TLE几个点,我们继续找原因!

我们看到题目中给出的提示,它有什么用呢?

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,cz,x,y,k;
int sum[],a[],lazy[]; //注意开4倍空间比较保险 void init(int node,int x,int y) //预处理一下
{
if(x==y) sum[node]=a[x]; //叶子结点,直接赋值
else
{
int mid=(x+y)>>;
init(node*,x,mid); //找左儿子
init(node*+,mid+,y); //找右儿子
sum[node]=sum[node*]^sum[node*+]; //更新父亲结点
}
lazy[node]=;
}
void pushdown(int node,int l,int r) //标记下传过程
{
int mid=(l+r)>>;
lazy[node*]^=lazy[node]; //下传给左儿子
lazy[node*+]^=lazy[node]; //下传给右儿子
sum[node*]^=lazy[node]*((mid-l+)%); //更新左儿子的sum,用到了上面讲的优化2:更新奇数次就是更新一次,更新偶数次就是没更新
sum[node*+]^=lazy[node]*((r-mid)%);
lazy[node]=; //注意清空,这里不是标记永久化
}
void add(int node,int l,int r,int x,int y,int k) //区间[x,y]的每个数都异或上k
{
if(l>=x&&r<=y) //当前分解的区间[l,r]被完全包含在[x,y]里的话,直接更新
{
sum[node]^=k*((r-l+)%); //优化2
lazy[node]^=k; //更新懒标记
return ;
}
pushdown(node,l,r); //先要标记下传
int mid=(l+r)>>;
if(x<=mid) add(node*,l,mid,x,y,k); //与左区间有交集就去找左区间
if(y>=mid+) add(node*+,mid+,r,x,y,k); //与右区间有交集就去找右区间
sum[node]=sum[node*]^sum[node*+]; //再更新父亲结点的sum
}
int ask(int node,int l,int r,int x,int y) //询问区间[x,y]内的异或和
{
if(l>=x&&r<=y) return sum[node]; //被[x,y]包含的话就直接返回
pushdown(node,l,r);
int res=,mid=(l+r)>>;
if(x<=mid) res^=ask(node*,l,mid,x,y); //与左区间有交集就去找左区间
if(y>=mid+) res^=ask(node*+,mid+,r,x,y); //与右区间有交集就去找右区间
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
init(,,n);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&cz,&x,&y);
if(cz==)
{
scanf("%d",&k); //[x,y]异或上k
add(,,n,x,y,k);
}
else printf("%d\n",ask(,,n,x,y)); //询问[x,y]的异或和
}
return ;
}

2019.6.28 校内测试 T4 【音乐会】达拉崩吧·上的更多相关文章

  1. T83312 【音乐会】达拉崩吧·上

    T83312 [音乐会]达拉崩吧·上 题解 线段树板子题 把原来的 + 变成 ^ 但是注意一下懒标记,这里讲一下小技巧 代码 #include<bits/stdc++.h> using n ...

  2. 2019.6.28 校内测试 T3 【音乐会】道路千万条

    大眼一看最下面的题意解释的话,发现这和洛谷P1310表达式的值挺像的,大概都是给定一些运算符号,让最后的表达式为true的概率,为false的概率啥的QwQ~: 然后这个题嘛?就是在所有的运算符中提溜 ...

  3. 2019.6.28 校内测试 T2 【音乐会】二重变革

    看到这个题之后,一个很暴力很直接的想法就是贴上题目中的代码然后交上去走人,但是很显然这是会TLE+MLE的,想想谁会这么傻把主要代码给你QwQ~: 其实这段代码是想告诉你一件事:用序列中的大数减去小数 ...

  4. 2019.6.28 校内测试 T1 Jelly的难题1

    这题面有点难理解,建议直接跳到题意解释那一部分(虽然我觉得解释的不大对,但按照解释来做确实能AC): 按照“题意解释”的思路来思考这个题,那么就十分的简单了: 1.首先要读入这个字符矩阵,可以用cin ...

  5. 2019.7.9 校内测试 T3 15数码问题

    这一次是交流测试?边交流边测试(滑稽 15数码问题 大家应该都玩过这个15数码的游戏吧,就在桌面小具库那里面哦. 一看到这个题就知道要GG,本着能骗点分的原则输出了 t 个无解,本来以为要爆零,没想到 ...

  6. 2019.7.9 校内测试 T2 极值问题

    这一次是交流测试?边交流边测试(滑稽 极值问题 乍一看这是一道数学题,因为1e9的数据让我暴力的心退却. 数学又不好,不会化简式子嘞,咋办? 不怕,咱会打表找规律.(考场上真的是打表找出了规律,打表打 ...

  7. 2019.7.9 校内测试 T1挖地雷

    这一次是交流测试?边交流边测试(滑稽 挖地雷 这个题是一个递推问题. 首先我们看第一个格子,因为它只影响了它的上面和右上面这两个地方是否有雷. 我们可以分3种情况讨论: 1. 第一个格子的数字是2: ...

  8. 【8.28校内测试】【区间DP】

    感受到了生活的艰辛QAQ...这才是真正的爆锤啊...(因为t1t3还没有理解所以只能贴t2叻QAQ 区间DP...爆哭把题理解错了,以为随着拿的东西越来越多,断点也会越来越多,出现可以选很多的情况Q ...

  9. 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解

    看到Day 2的题真的想打死zay了,忒难了QwQ~ T1 江城唱晚 这明显是个求方案数的计数问题,一般的套路是DP和组合数学. 正如题目中所说,这个题是一个 math 题.      ----zay ...

随机推荐

  1. django中使用redis保存session(转)

    原文:https://blog.csdn.net/Enjolras_fuu/article/details/79661582 Django-redis-session官网:https://pypi.o ...

  2. Optional 理解

    目录 Optional 理解 1. 含义 2. Optional 类中方法 3. Optional 对象不应该作为方法参数 Optional 理解 1. 含义 Optional 是一个容器对象,该容器 ...

  3. c#入门学习笔记

    Hello World //打印语句 Console.WriteLine("Hello World"); //暂停 Console.ReadKey(); 数据类型 1.值类型 by ...

  4. WPF 自定义一个控件,当点击按钮是触发到ViewModel(业务逻辑部分)和Xaml路由事件(页面逻辑部分)

    #region - 用于绑定ViewModel部分 - public ICommand Command { get { return (ICommand)GetValue(CommandPropert ...

  5. 九、小程序 Redux详解与在小程序中怎么使用(action和reducers)

    什么是Redux ​ Redux我们可以把它理解成一个状态管理器,可以把状态(数据)存在Redux中,以便增.删.改.例如: 从服务器上取一个收藏列表,就可以把取回来的列表数据用Redux管理,多个页 ...

  6. 四大伪类,css鼠标样式设置,reset操作,静止对文本操作

    07.31自我总结 一.a标签的四大伪类 a:link{样式} 未访问时的状态(鼠标点击前显示的状态) a:hover{样式} 鼠标悬停时的状态 a:visited{样式} 已访问过的状态(鼠标点击后 ...

  7. Docker多阶段构建实战(multi-stage builds)

    在编写Dockerfile构建docker镜像时,常遇到以下问题: RUN命令会让镜像新增layer,导致镜像变大,虽然通过&&连接多个命令能缓解此问题,但如果命令之间用到docker ...

  8. [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

    本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  9. 【ASE模型组】Hint::neural 模型与case study

    模型 基于搜索的提示系统 我们的系统用Pycee针对语法错误给出提示.然而,对于语法正确.结果错误的代码,我们需要另外的解决方式.因此,我们维护一些 (错误代码, 相应提示) 的数据,该数据可以由我们 ...

  10. flume 1.7在windows下的安装部署与测试运行

    一.安装 安装java,配置环境变量. 安装flume,下载地址,下载后直接解压即可. 二.运行 创建配置文件:在解压后的文件 apache-flume-1.7.0-bin\conf下创建一个exam ...