https://www.lydsy.com/JudgeOnline/problem.php?id=5312

Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护神挡住了去路,守护神给出了一个问题,只有答对了问题才能进入,守护神给出了一个自然数序列a,每次有一下三种操作。
1,给出l,r,x,将序列l,r之间的所有数都 and x
2,给出l,r,x,将序列l,r之间的所有数都 or x
3,给出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:冒险——题解的更多相关文章

  1. bzoj5312: 冒险(势能均摊线段树)

    题目链接 BZOJ5312: 冒险 题解 如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的 对于每次操作,在某些位上的值,对于整个区间影响是相同的,对 ...

  2. bzoj5312 冒险(吉司机线段树)题解

    题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 按位与\(x\) \(2.\)区间\([L,R]\) 按位或\(x\) \(3.\)区间\([L,R]\) 询问最大值 ...

  3. BZOJ5312 冒险(线段树)

    记录区间and/or,修改时如果对整个区间影响都相同就打标记,否则递归.复杂度不太会证. #include<iostream> #include<cstdio> #includ ...

  4. BZOJ5312: 冒险【线段树】【位运算】

    Description Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护神挡住了去路,守护神给出了一个问题, 只有答对了问题才能进入,守护神给出了一个自然数 ...

  5. BZOJ5312 冒险(势能线段树)

    BZOJ题目传送门 表示蒟蒻并不能一眼看出来这是个势能线段树. 不过仔细想想也并非难以理解,感性理解一下,在一个区间里又与又或,那么本来不相同的位也会渐渐相同,线段树每个叶子节点最多修改\(\log ...

  6. [BZOJ5312]冒险

    bzoj CSAcademy description 一个序列\(a_i\),支持区间与一个数,区间或一个数,求区间最大值. \(n,m\le2\times10^5\) sol 线段树每个节点上维护区 ...

  7. bzoj 4695: 最假女选手 && Gorgeous Sequence HDU - 5306 && (bzoj5312 冒险 || 小B的序列) && bzoj4355: Play with sequence

    算导: 核算法 给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量. 当实际代价小于摊还代价时,增加等于差额的 ...

  8. BZOJ5312 冒险 势能分析、线段树

    传送门 区间位赋值.区间求最大值似乎是不能够像一般的线段树一样直接打标记的,但是直接暴力也太没有面子了. 我们考虑优化一下暴力:如果说线段树的一段区间内在当前修改的所有位置上所有数都是相同的,那么这个 ...

  9. 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)

    线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...

随机推荐

  1. 「专题训练」Air Raid(HDU-1151)

    题目 在一个城市里有\(n\)个地点和\(k\)条道路,道路是无环的(也就是说一定可以二分染色--回路长度为偶数0),现在伞兵需要去n个地点视察,只能沿着路的方向走,问最少需要多少伞兵. 分析 这是什 ...

  2. 微信小程序如何性能测试?

    背景: 微信小程序作为手机页面的一种,相比传统的网站和应用来说存在比较特殊的地方: 1.  开发者往往对程序做了限制,只能通过微信客户端访问 2.  通过微信的Oauth进行认证 这样往往会导致我们的 ...

  3. 通过 Python_Faker 生成测试数据

    通过 Python_Faker 生成测试数据 一.介绍 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,你不可能通过手工来生成(最傻的方法)可能 ...

  4. jmeter的脚本增强之参数化

    jmeter作为一款开源的测试工具,功能广泛,深受测试同胞们的喜爱,这次来讲讲关于如何参数化及其方式.那为什么要进行一个参数化呢,如做压测时,要有大量的数据来模拟用户的真实场景,像登录页面操作,系统是 ...

  5. adb 常用命令及操作

    获取序列号: adb get-serialno 查看连接计算机的设备: adb devices 重启机器: adb reboot 重启到bootloader,即刷机模式: adb reboot boo ...

  6. mapReduce入门教程

    什么是MapReduce MapReduce是Google提出的一个软件架构,用于大规模数据集(大于1TB)的并行运算.概念"Map(映射)"和"Reduce(归纳)&q ...

  7. 论文阅读之Joint cell segmentation and tracking using cell proposals

    论文提出了一种联合细胞分割和跟踪方法,利用细胞segmentation proposals创建有向无环图,然后在该图中迭代地找到最短路径,为单个细胞提供分割,跟踪和事件. 3. PROPOSAL GE ...

  8. 火狐metamask账号

    火狐metamask lock trophy pyramid sunny aim inmate body sense sing castle cinnamon cram

  9. HDU 3467 Song of the Siren(圆交)

    Problem Description In the unimaginable popular DotA game, a hero Naga Siren, also known as Slithice ...

  10. POJ 2455 Secret Milking Machine(最大流+二分)

    Description Farmer John is constructing a new milking machine and wishes to keep it secret as long a ...