BZOJ5312:冒险——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5312
Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护神挡住了去路,守护神给出了一个问题,只有答对了问题才能进入,守护神给出了一个自然数序列a,每次有一下三种操作。1,给出l,r,x,将序列l,r之间的所有数都 and x2,给出l,r,x,将序列l,r之间的所有数都 or x3,给出l,r,询问l,r之间的最大值
(下划线以前都是废话)
没有什么好方法,因为最大值的变化不能用简单的and x以及or x,但是我们能够暴力线段树维护,然而毫无疑问是TLE。
于是我们的目标是直接能够mx[a]and/or=x以此维护。
我们考虑能不能用吉司机线段树维护一下。
让我们想一个naive的想法,即我and x则区间全变成x,or x则区间全变成x。
于是我们需要多记录两个区间and值和区间or值,如果区间and值and x=x则我们全变x,如果区间or值or x=x则我们全变x。
当然会TLE……
————————————————————————
我们继续想,区间内的数在经过多次操作后其公共的1的数量占每个数的1的个数的比重会越来越大并最终为100%。
于是我们要利用这个想法,当然这里给出结论:(区间or值xor区间and值)and x=0时我们更新。
(括号内的东西代表了各数的不公有的1,也就是说x不能有它们不公有的1,剩下的还请读者自行推导其正确性。)
此时mx[a]and/or=x即可(显然的),同时我们还可对区间and值和or值也and/or=x来更新(不显然,但懒得证了)。
现在就很像吉司机线段树了,但是对于势能分析我要写个大大的坑字在这里。
- #include<map>
- #include<cmath>
- #include<stack>
- #include<queue>
- #include<cstdio>
- #include<cctype>
- #include<vector>
- #include<cstdlib>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- const int INF=(<<)-;
- const int N=2e5+;
- inline int read(){
- int X=,w=;char ch=;
- while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
- while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
- return w?-X:X;
- }
- int n,m,b[N],mx[N*],ran[N*],ror[N*],lza[N*],lzo[N*];
- inline void upt(int a){
- mx[a]=max(mx[a<<],mx[a<<|]);
- ran[a]=ran[a<<]&ran[a<<|];
- ror[a]=ror[a<<]|ror[a<<|];
- }
- void build(int a,int l,int r){
- lza[a]=INF,lzo[a]=;
- if(l==r){
- mx[a]=b[l];ran[a]=b[l];ror[a]=b[l];
- return;
- }
- int mid=(l+r)>>;
- build(a<<,l,mid);build(a<<|,mid+,r);
- upt(a);
- }
- inline void push(int a){
- int ls=a<<,rs=a<<|;
- if(lzo[a]!=){
- mx[ls]|=lzo[a];mx[rs]|=lzo[a];
- ran[ls]|=lzo[a];ran[rs]|=lzo[a];
- ror[ls]|=lzo[a];ror[rs]|=lzo[a];
- lza[ls]|=lzo[a];lza[rs]|=lzo[a];
- lzo[ls]|=lzo[a];lzo[rs]|=lzo[a];
- lzo[a]=;
- }
- if(lza[a]!=INF){
- mx[ls]&=lza[a];mx[rs]&=lza[a];
- ran[ls]&=lza[a];ran[rs]&=lza[a];
- ror[ls]&=lza[a];ror[rs]&=lza[a];
- lza[ls]&=lza[a];lza[rs]&=lza[a];
- lza[a]=INF;
- }
- }
- void mdy(int a,int l,int r,int l1,int r1,int x,bool k){
- if(r<l1||r1<l)return;
- if(l1<=l&&r<=r1&&(!((ran[a]^ror[a])&x))){
- if(!k){mx[a]&=x;ran[a]&=x;ror[a]&=x;lza[a]&=x;}
- else{mx[a]|=x;ran[a]|=x;ror[a]|=x;lza[a]|=x;lzo[a]|=x;}
- return;
- }
- int mid=(l+r)>>;
- push(a);
- mdy(a<<,l,mid,l1,r1,x,k);mdy(a<<|,mid+,r,l1,r1,x,k);
- upt(a);
- }
- int qry(int a,int l,int r,int l1,int r1){
- if(r<l1||r1<l)return -;
- if(l1<=l&&r<=r1)return mx[a];
- int mid=(l+r)>>;
- push(a);
- return max(qry(a<<,l,mid,l1,r1),qry(a<<|,mid+,r,l1,r1));
- }
- int main(){
- n=read(),m=read();
- for(int i=;i<=n;i++)b[i]=read();
- build(,,n);
- while(m--){
- int op=read(),x=read(),y=read();
- if(op==)mdy(,,n,x,y,read(),);
- if(op==)mdy(,,n,x,y,read(),);
- if(op==)printf("%d\n",qry(,,n,x,y));
- }
- return ;
- }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ5312:冒险——题解的更多相关文章
- bzoj5312: 冒险(势能均摊线段树)
题目链接 BZOJ5312: 冒险 题解 如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的 对于每次操作,在某些位上的值,对于整个区间影响是相同的,对 ...
- bzoj5312 冒险(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 按位与\(x\) \(2.\)区间\([L,R]\) 按位或\(x\) \(3.\)区间\([L,R]\) 询问最大值 ...
- BZOJ5312 冒险(线段树)
记录区间and/or,修改时如果对整个区间影响都相同就打标记,否则递归.复杂度不太会证. #include<iostream> #include<cstdio> #includ ...
- BZOJ5312: 冒险【线段树】【位运算】
Description Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护神挡住了去路,守护神给出了一个问题, 只有答对了问题才能进入,守护神给出了一个自然数 ...
- BZOJ5312 冒险(势能线段树)
BZOJ题目传送门 表示蒟蒻并不能一眼看出来这是个势能线段树. 不过仔细想想也并非难以理解,感性理解一下,在一个区间里又与又或,那么本来不相同的位也会渐渐相同,线段树每个叶子节点最多修改\(\log ...
- [BZOJ5312]冒险
bzoj CSAcademy description 一个序列\(a_i\),支持区间与一个数,区间或一个数,求区间最大值. \(n,m\le2\times10^5\) sol 线段树每个节点上维护区 ...
- bzoj 4695: 最假女选手 && Gorgeous Sequence HDU - 5306 && (bzoj5312 冒险 || 小B的序列) && bzoj4355: Play with sequence
算导: 核算法 给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量. 当实际代价小于摊还代价时,增加等于差额的 ...
- BZOJ5312 冒险 势能分析、线段树
传送门 区间位赋值.区间求最大值似乎是不能够像一般的线段树一样直接打标记的,但是直接暴力也太没有面子了. 我们考虑优化一下暴力:如果说线段树的一段区间内在当前修改的所有位置上所有数都是相同的,那么这个 ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
随机推荐
- CentOS下安装Tomcat环境
一.安装JAVA环境 1.安装JAVA mkdir -p /usr/local/java 下载jdk1.7.0_67.tar.gz包,并解压到 tar xf jdk1.7.0_67.tar.gz -C ...
- webpack中Development和Production模式的区分打包
当我们在开发一个项目的时候,我们一般用development这个环境进行项目的开发,在这个环境下,webpack使用dev-server,帮我们启用一个服务器,然后这个服务器里面还集成了一些,比如hm ...
- 对网页进行截图(selenium)
import os def insert_img(driver,file_name): #获取当前路径,并转换为字符串 base_dir=str(os.path.dirname(__file__)) ...
- Allure--自动化测试报告生成
之前尝试使用过testNG自带的测试报告.优化过reportNG的测试报告,对这两个报告都不能满意.后经查找资料,发现有个神器: Allure(已经有allure2了,笔者使用的就是allure2), ...
- 前端开发工程师 - 02.JavaScript程序设计 - 第1章.基础篇
第1章--基础篇 JS介绍 html 网页的内容:css 网页的样式:javascript 网页的行为 i.e. hello world <!DOCTYPE html> <html& ...
- lintcode514 栅栏染色
栅栏染色 我们有一个栅栏,它有n个柱子,现在要给柱子染色,有k种颜色可以染.必须保证不存在超过2个相邻的柱子颜色相同,求有多少种染色方案. 注意事项 n和k都是非负整数 您在真实的面试中是否遇到过这个 ...
- Java学习笔记-10.io流
1.输入流,只能从中读取数据,而不能向其写出数据.输出流,只能想起写入字节数据,而不能从中读取. 2.InputStream的类型有: ByteArrayInputStream 包含一个内存缓冲区,字 ...
- html常用小知识
请求重定向:加载页面之后,除了用js做重定向之外,我们还可以直接用<meta>标签做重定向. <meta http-equiv="refresh" content ...
- DeepLearning - Forard & Backward Propogation
In the previous post I go through basic 1-layer Neural Network with sigmoid activation function, inc ...
- 物联网常见通信协议RFID、NFC、Bluetooth、ZigBee等梳理
1 概述 在上一篇文章<物联网常见通信协议与通讯协议梳理[上]-通讯协议>中,对物联网常用通信协议和通讯协议作了区分,并对通讯协议进行了分享:本文将对常用的通信协议进行剖析,重点面向市场 ...