2019.6.28 校内测试 T4 【音乐会】达拉崩吧·上



考试的一道附加题~
一看题目描述:把区间[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 【音乐会】达拉崩吧·上的更多相关文章
- T83312 【音乐会】达拉崩吧·上
T83312 [音乐会]达拉崩吧·上 题解 线段树板子题 把原来的 + 变成 ^ 但是注意一下懒标记,这里讲一下小技巧 代码 #include<bits/stdc++.h> using n ...
- 2019.6.28 校内测试 T3 【音乐会】道路千万条
大眼一看最下面的题意解释的话,发现这和洛谷P1310表达式的值挺像的,大概都是给定一些运算符号,让最后的表达式为true的概率,为false的概率啥的QwQ~: 然后这个题嘛?就是在所有的运算符中提溜 ...
- 2019.6.28 校内测试 T2 【音乐会】二重变革
看到这个题之后,一个很暴力很直接的想法就是贴上题目中的代码然后交上去走人,但是很显然这是会TLE+MLE的,想想谁会这么傻把主要代码给你QwQ~: 其实这段代码是想告诉你一件事:用序列中的大数减去小数 ...
- 2019.6.28 校内测试 T1 Jelly的难题1
这题面有点难理解,建议直接跳到题意解释那一部分(虽然我觉得解释的不大对,但按照解释来做确实能AC): 按照“题意解释”的思路来思考这个题,那么就十分的简单了: 1.首先要读入这个字符矩阵,可以用cin ...
- 2019.7.9 校内测试 T3 15数码问题
这一次是交流测试?边交流边测试(滑稽 15数码问题 大家应该都玩过这个15数码的游戏吧,就在桌面小具库那里面哦. 一看到这个题就知道要GG,本着能骗点分的原则输出了 t 个无解,本来以为要爆零,没想到 ...
- 2019.7.9 校内测试 T2 极值问题
这一次是交流测试?边交流边测试(滑稽 极值问题 乍一看这是一道数学题,因为1e9的数据让我暴力的心退却. 数学又不好,不会化简式子嘞,咋办? 不怕,咱会打表找规律.(考场上真的是打表找出了规律,打表打 ...
- 2019.7.9 校内测试 T1挖地雷
这一次是交流测试?边交流边测试(滑稽 挖地雷 这个题是一个递推问题. 首先我们看第一个格子,因为它只影响了它的上面和右上面这两个地方是否有雷. 我们可以分3种情况讨论: 1. 第一个格子的数字是2: ...
- 【8.28校内测试】【区间DP】
感受到了生活的艰辛QAQ...这才是真正的爆锤啊...(因为t1t3还没有理解所以只能贴t2叻QAQ 区间DP...爆哭把题理解错了,以为随着拿的东西越来越多,断点也会越来越多,出现可以选很多的情况Q ...
- 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
看到Day 2的题真的想打死zay了,忒难了QwQ~ T1 江城唱晚 这明显是个求方案数的计数问题,一般的套路是DP和组合数学. 正如题目中所说,这个题是一个 math 题. ----zay ...
随机推荐
- Mish:一个新的SOTA激活函数,ReLU的继任者
Mish:一个新的SOTA激活函数,ReLU的继任者 CVer 昨天 以下文章来源于AI公园 ,作者ronghuaiyang AI公园 专注分享干货的AI公众号,图像处理,NLP,深度学习,机器学 ...
- sql注入测试(1)---概念概述
在进行java web 测试时,经常会忽略的测试种类就是sql注入测试,这类缺陷造成的原因是开发技术在这方面欠缺的表现,虽然不常见,但一旦有这类缺陷,就很因此对运营的数据造成很多不必要的损失,所以,还 ...
- JSQI网站大事表 | Website Landmark
2016-07-01 网站前身jsqi.50vip.com上线.2016-07-12 购买jsqi.org域名,替代之前的二级域名.2016-12-12 申请ChinaDMOZ收录,瞬间申请通过.20 ...
- 动态规划-最大算式 蓝桥杯ALGO-116
问题描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号 ...
- C# Winfrom DataGridView常用设置
DataGridView常用设置 using System; using System.Collections.Generic; using System.Drawing; using System. ...
- Linux基本命令-chmod
chmod命令用来变更文件或目录的权限.在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件 ...
- OpenGL ES on iOS --- 统一变量(Uniform)和统一变量块(UBO)
简介 Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同. 首先,uniform是全局的(Global).全局意味着uniform变量必须在每个着 ...
- Ubuntu系统---又显示nvidia-smi 未找到命令
Ubuntu系统---又显示nvidia-smi 未找到命令 本来nvidia驱动+CUDA安装好用,两次遇到开机发现字体异常,不用合计,是显卡驱动的问题.一查,确实是nvidia-smi 未找到命令 ...
- Spark2 jar存档
spark.yarn.archive需要手动将spark应用依赖jar上传到hdfs,该属性可以避免每一次运行spark应用时都重复打zip包上传到hdfs. 官网http://spark.apach ...
- 51Nod - 1714 B君的游戏
每个数的SG值之和他有多少个1相关 打表复杂度:找K个有序的<n的非负数的复杂度为nk/(k!) 则这题的SG打表复杂度为648/7! 为1e10左右 void dfs(int cur, int ...