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/+

+++++++++++++++++++++++++++++++++++++++++++

最新文章

  1. [转] 评 WOW技能天赋设计
  2. c#.net 使用NPOI导入导出标准Excel (asp.net winform csharp)
  3. Android动画学习笔记-Android Animation
  4. iOS获取当前app的名称和版本号
  5. 高级屏幕空间反射: Screen Space Reflection (SSR)
  6. 【原创】C#搭建足球赛事资料库与预测平台(5) 赔率数据表设计1
  7. [py]导入模块3种方法
  8. 【Java 基础篇】【第九课】继承
  9. [转载] Linux 文件系统结构介绍
  10. 关于JDBC 连接Access 数据库
  11. 使用Apache 的lib进行List、Set、数组之间的转换(转)
  12. meta便签的用法
  13. Visual Studio跨平台开发实战(4) - Xamarin Android基本控制项介绍
  14. 面试常问的几个排序和查找算法,PHP实现
  15. Codeforces379 F. New Year Tree
  16. python2 与 python3 语法区别
  17. node封装mysql操作
  18. jvm垃圾回收机制和常见算法
  19. Cocos2dx 小技巧(十四)ScrollView实现缩放效果
  20. Django——REST framework

热门文章

  1. iOS SSL Pinning 保护你的 API
  2. Farpoint使用一点小总结
  3. hdu1106 排序(字符串分割,strtok+sscanf)
  4. Python 默认参数值
  5. Android开发-API指南-&lt;permission-tree&gt;
  6. appium 元素定位与操作:
  7. Ubuntu16.04安装wps办公软件解决文字缺失
  8. 【机器学习】多项式回归sklearn实现
  9. STM32单片机是如何启动的?
  10. JavaScript筑基篇(二)-&gt;JavaScript数据类型