考试的一道附加题~

一看题目描述:把区间[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. Neo4j查询语句总结

    最近一直在做图数据库的相关工作,对neo4j的查询语言Cypher使用较多,故在此总结记录.Cypher作为图数据库的查询语言,感觉和关系型数据库的查询语言sql差不多吧. 1.如何找到一个节点x,x ...

  2. [Vue]vue中路由重定向redirect

    1.重定向的地址不需要接收参数 const routes = [ { path: '/', redirect: '/index'}, { path: '/index', component: inde ...

  3. WebSocket协议探究(二)

    一 复习和目标 1 复习 协议概述: WebSocket内置消息定界并且全双工通信 WebSocket使用HTTP进行协议协商,协商成功使用TCP连接进行传输数据 WebScoket数据格式支持二进制 ...

  4. 【原创】大叔经验分享(94)jdbc连接mysql、sqlserver、oracle

    Mysql driver下载:https://mvnrepository.com/artifact/mysql/mysql-connector-java import java.sql.*; publ ...

  5. 使用shared memory 计算矩阵乘法 (其实并没有加速多少)

    #include "cuda_runtime.h" #include "device_launch_parameters.h" #include "d ...

  6. ARM微控制器与嵌入式系统

    个牛人在ARM实现嵌入式系统的过程 第一章  概览 1.1课程概览 认识ARM嵌入式系统(什么是ARM?什么是嵌入式系统?) 备战智能车 在科技活动中玩起来 积累计算机.电路基础知识 1.2如何学好嵌 ...

  7. win10下PLSQL Developer 连接ubuntu上安装的oracle 11g

    说明:过程记录的不是很相信,只记录基本步骤.并不适合想一步一步照做的同学. win10下需要的操作 1.微软官网下载instantclient,然后接到到本地一个文件夹,注意路径不要又空格,中文和括号 ...

  8. 脱壳系列—— *加密脱壳(Android使用手册破解)

    作者:i春秋作家HAI_ZHU 0×00 前言 好久没有写文了,要好好开动一下了.很多事情要忙.这篇文章本来很早之前就要写的,但是因为很多事情就拖了很久. 前置内容 HAI_使用手册 知识总结 0×0 ...

  9. MRC下delegate 野指针问题

    最近项目开发中,临时被调去修复一个页面返回时crash的问题.出现这个问题的原因也很巧合,正好服务地址在同事电脑上,也正巧网络请求响应时间狂慢!一个请求发出去回来的时间是40秒左右,要是在线上,肯定会 ...

  10. ASE19团队项目 beta阶段 model组 scrum2 记录

    本次会议于12月3日,19时整在微软北京西二号楼sky garden召开,持续10分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...