bzoj5312 冒险(吉司机线段树)题解
题意:
已知\(n\)个数字,进行以下操作:
- \(1.\)区间\([L,R]\) 按位与\(x\)
- \(2.\)区间\([L,R]\) 按位或\(x\)
- \(3.\)区间\([L,R]\) 询问最大值
思路:
吉司机线段树。
我们按位考虑,维护区间或\(\_or\)和区间与\(\_and\),那么得到区间非公有的\(1\)为\((\_or \oplus \_and)\),那么如果对所有的非公有的\(1\)影响都一样就不会对最大值有影响,那么就直接打标机,否则继续往下更新。即
\]
时就直接打标记。
代码:
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn = 2e5 + 5;
const int MAXM = 3e6;
const ll MOD = 998244353;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
#define lson (rt << 1)
#define rson (rt << 1 | 1)
inline bool read(int &num){
char in;
bool IsN=false;
in = getchar();
if(in == EOF) return false;
while(in != '-' && (in < '0' || in > '9')) in = getchar();
if(in == '-'){ IsN = true; num = 0;}
else num = in - '0';
while(in = getchar(),in >= '0' && in <= '9'){
num *= 10, num += in-'0';
}
if(IsN) num = -num;
return true;
}
int a[maxn], all = (1 << 21) - 1;
int _or[maxn << 2], _and[maxn << 2], Max[maxn << 2];
int lazya[maxn << 2], lazyo[maxn << 2];
inline void pushup(int rt){
_or[rt] = _or[lson] | _or[rson];
_and[rt] = _and[lson] & _and[rson];
Max[rt] = max(Max[lson], Max[rson]);
}
inline void pushdown(int rt, int l, int r){
int m = (l + r) >> 1;
if(lazya[rt] != all){
Max[lson] &= lazya[rt];
Max[rson] &= lazya[rt];
_or[lson] &= lazya[rt];
_or[rson] &= lazya[rt];
_and[lson] &= lazya[rt];
_and[rson] &= lazya[rt];
lazya[lson] &= lazya[rt];
lazya[rson] &= lazya[rt];
lazyo[lson] &= lazya[rt];
lazyo[rson] &= lazya[rt];
lazya[rt] = all;
}
if(lazyo[rt] != 0){
Max[lson] |= lazyo[rt];
Max[rson] |= lazyo[rt];
_or[lson] |= lazyo[rt];
_or[rson] |= lazyo[rt];
_and[lson] |= lazyo[rt];
_and[rson] |= lazyo[rt];
lazya[lson] |= lazyo[rt];
lazya[rson] |= lazyo[rt];
lazyo[lson] |= lazyo[rt];
lazyo[rson] |= lazyo[rt];
lazyo[rt] = 0;
}
}
void build(int l, int r, int rt){
lazya[rt] = all, lazyo[rt] = 0;
if(l == r){
_and[rt] = _or[rt] = Max[rt] = a[l];
return;
}
int m = (l + r) >> 1;
build(l, m, lson);
build(m + 1, r, rson);
pushup(rt);
}
void update(int L, int R, int l, int r, int op, int x, int rt){
if(L <= l && R >= r){
if(op == 1){ //&
if(((_or[rt] ^ _and[rt]) & x) == 0 || ((_or[rt] ^ _and[rt]) & x) == (_or[rt] ^ _and[rt])){
Max[rt] &= x;
_or[rt] &= x;
_and[rt] &= x;
lazya[rt] &= x;
lazyo[rt] &= x;
return;
}
}
else{ //|
if(((_or[rt] ^ _and[rt]) & x) == 0 || ((_or[rt] ^ _and[rt]) & x) == (_or[rt] ^ _and[rt])){
Max[rt] |= x;
_or[rt] |= x;
_and[rt] |= x;
lazya[rt] |= x;
lazyo[rt] |= x;
return;
}
}
}
int m = (l + r) >> 1;
pushdown(rt, l, r);
if(L <= m)
update(L, R, l, m, op, x, lson);
if(R > m)
update(L, R, m + 1, r, op, x, rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt){
if(L <= l && R >= r){
return Max[rt];
}
pushdown(rt, l, r);
int m = (l + r) >> 1, MAX = -INF;
if(L <= m)
MAX = max(MAX, query(L, R, l, m, lson));
if(R > m)
MAX = max(MAX, query(L, R, m + 1, r, rson));
return MAX;
}
int main(){
int n, m;
read(n), read(m);
for(int i = 1; i <= n; i++) read(a[i]);
build(1, n, 1);
while(m--){
int op, l, r, x;
read(op), read(l), read(r);
if(op < 3) read(x);
if(op < 3){
update(l, r, 1, n, op, x, 1);
}
else{
printf("%d\n", query(l, r, 1, n, 1));
}
}
return 0;
}
bzoj5312 冒险(吉司机线段树)题解的更多相关文章
- bzoj4355 Play with sequence(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 赋值为\(x\) \(2.\)区间\([L,R]\) 赋值为\(max(a[i] + x, 0)\) \(3.\)区间 ...
- bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...
- BZOJ4355: Play with sequence(吉司机线段树)
题意 题目链接 Sol 传说中的吉司机线段树??感觉和BZOJ冒险那题差不多,就是强行剪枝... 这题最坑的地方在于对于操作1,$C >= 0$, 操作2中需要对0取max,$a[i] > ...
- HDU - 5306 Gorgeous Sequence (吉司机线段树)
题目链接 吉司机线段树裸题... #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3 ...
- UVALive - 4108 SKYLINE (吉司机线段树)
题目链接 题意:在一条直线上依次建造n座建筑物,每座建筑物建造完成后询问它在多长的部分是最高的. 比较好想的方法是用线段树分别维护每个区间的最小值mi和最大值mx,当建造一座高度为x的建筑物时,若mi ...
- HDU - 6315 吉司机线段树
题意:给出a,b数组,区间上两种操作,给\(a[L,R]\)+1s,或者求\(\sum_{i=l}^{r}a_i/b_i\) 一看就知道是吉司机乱搞型线段树(低配版),暴力剪枝就好 维护区间a的最大值 ...
- BZOJ5312 冒险(势能线段树)
BZOJ题目传送门 表示蒟蒻并不能一眼看出来这是个势能线段树. 不过仔细想想也并非难以理解,感性理解一下,在一个区间里又与又或,那么本来不相同的位也会渐渐相同,线段树每个叶子节点最多修改\(\log ...
- HDU 5306 吉司机线段树
思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include ...
- hdu6521 吉司机线段树
http://acm.hdu.edu.cn/showproblem.php?pid=6521 待填 代码 #include<bits/stdc++.h> #define ls o<& ...
随机推荐
- [分享] 最流行的 10 个 JavaScript 库
1. Lodash https://github.com/lodash/lodash 一个工具库,用得还蛮多. 2. Chalk https://github.com/chalk/chalk 给终端加 ...
- PW6513高压40V的LDO芯片,SOT89封装
一般说明 PW6513系列是一款高精度,高输入电压,低静态电流,高速,低具有高纹波抑制的线性稳压器.输入电压高达40V,负载电流为在电压=5V和VIN=7V时高达300mA.该设备采用BCD工艺制造. ...
- 响应式编程库RxJava初探
引子 在读 Hystrix 源码时,发现一些奇特的写法.稍作搜索,知道使用了最新流行的响应式编程库RxJava.那么响应式编程究竟是怎样的呢? 本文对响应式编程及 RxJava 库作一个初步的探索. ...
- 二本学生拿到腾讯大厂offer的成长记录
本人迈莫,是在20年以春招实习生的身份进入鹅厂,经过重重波折,最终成为鹅仔一份子.接下来我会以我亲生经历为例,分享一下普通大学的学生也是可以进去大厂,拭目以待!!! 初入大学 惨遭毒打 时间倒回到17 ...
- django中的几种返回模版的方式
redirect方法-----(重定向) # 首先导入redirect方法, from django.shortcuts import redirect 在函数中写一个返回值 return redir ...
- 【转载】HTTP 协议详细介绍
背景 当你在浏览器地址栏敲入"http://www.cnblogs.com/",然后猛按回车,呈现在你面前的,将是博客园的首页了(这真是废话,你会认为这是理所当然的).作为一个开发 ...
- 一文打尽 Linux/Windows端口复用实战
出品|MS08067实验室(www.ms08067.com) 本文作者:Spark(Ms08067内网安全小组成员) 定义:端口复用是指不同的应用程序使用相同端口进行通讯. 场景:内网渗透中,搭建隧道 ...
- FreeWheel核心业务团队混沌工程实践之路
https://mp.weixin.qq.com/s/0monDPkAlMk7Yhq9swW7gQ 原创 郭彦梅 InfoQ 2020-11-17
- 长连接 短连接 RST报文
https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...
- python中贪婪与非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符: 非贪婪则相反,总是尝试匹配尽可能少的字符. 在"*","?", ...