首先我们考虑,对于And 和 Or 操作,对于操作位上只有And 0 和 Or 1 是有效果的。

我们注意到如果区间内需要改动的操作位上的数字都相同,那么是可以区间取与以及区间取或的。

那其实可以维护出这个区间的$区间与x和区间或y$

我们考虑 $某一位上 x\;  xor \; y == 1 时$

必定是$x 那一位上 是0 \; y 那一位上是1$

因为显然 $如果x那一位上是1,那么y那一位上必然是1, y那一位上是0, x 那一位上必然是0$

那我们再考虑区间与的操作,我们令 $S = (1 << 31) - 1, 令val 表示需要与的数$

当 $(x \; xor \; y) \; and \; (S - val) == 0 的时候$

这个时候可以理解为在不需要与0的位置上,这个区间内都是1或者都是0,即这些不相关位对我们的区间取与操作不会有影响。

再考虑如何标记$lazy, 对And 和 Or 分别设置一个lazyA 和 lazyO $

$我们注意到,要取与的时候,把lazyA 一并与上, 并且把lazyO也要与上$

取或的时候只给$lazyO$取或就可以。

区间取或的操作分析同理。

再简陋的证明一下复杂度:

假设我们考虑要处理的一段区间不能进行区间处理,需要一位一位处理,但是我们这次处理之后这一段区间就可以区间处理了

再考虑,对于一段已经完好的区间,我们对它区间处理,它就会分成三段,但实际上这次的处理是$log的$

再考虑下一次处理,实际上两头又是好的,感觉又是$log$..

好吧 不口胡了,还是放官方的复杂度证明吧。。

https://csacademy.com/contest/round-70/task/and-or-max/solution

 #include <bits/stdc++.h>
using namespace std; #define N 200010
int n, q, arr[N], S = ( << ) - ; struct SEG
{
struct node
{
int Max, A, O, lazyA, lazyO;
node() {}
node(int x)
{
Max = A = O = x;
lazyA = S;
lazyO = ;
}
node operator + (const node &r) const
{
node res = node();
res.Max = max(Max, r.Max);
res.A = A & r.A;
res.O = O | r.O;
return res;
}
void add(int And, int Or)
{
Max = Max & And | Or;
A = A & And | Or;
O = O & And | Or;
lazyA = lazyA & And;
lazyO = lazyO & And | Or;
}
}a[N << ];
void build(int id, int l, int r)
{
if (l == r)
{
a[id] = node(arr[l]);
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
a[id] = a[id << ] + a[id << | ];
}
void pushdown(int id)
{
if (a[id].lazyA != S || a[id].lazyO)
{
a[id << ].add(a[id].lazyA, a[id].lazyO);
a[id << | ].add(a[id].lazyA, a[id].lazyO);
a[id].lazyA = S;
a[id].lazyO = ;
}
}
void updateA(int id, int l, int r, int ql, int qr, int val)
{
if (l >= ql && r <= qr && !((a[id].A ^ a[id].O) & (S ^ val)))
{
a[id].add(val, );
return;
}
pushdown(id);
int mid = (l + r) >> ;
if (ql <= mid) updateA(id << , l, mid, ql, qr, val);
if (qr > mid) updateA(id << | , mid + , r, ql, qr, val);
a[id] = a[id << ] + a[id << | ];
}
void updateO(int id, int l, int r, int ql, int qr, int val)
{
if (l >= ql && r <= qr && !((a[id].A ^ a[id].O) & val))
{
a[id].add(S, val);
return;
}
pushdown(id);
int mid = (l + r) >> ;
if (ql <= mid) updateO(id << , l, mid, ql, qr, val);
if (qr > mid) updateO(id << | , mid + , r, ql, qr, val);
a[id] = a[id << ] + a[id << | ];
}
int query(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr) return a[id].Max;
pushdown(id);
int mid = (l + r) >> ;
int res = ;
if (ql <= mid) res = max(res, query(id << , l, mid, ql, qr));
if (qr > mid) res = max(res, query(id << | , mid + , r, ql, qr));
a[id] = a[id << ] + a[id << | ];
return res;
}
}seg; void Run()
{
while (scanf("%d%d", &n, &q) != EOF)
{
for (int i = ; i <= n; ++i) scanf("%d", arr + i);
seg.build(, , n);
for (int qq = , op, l, r, x; qq <= q; ++qq)
{
scanf("%d%d%d", &op, &l, &r);
if (op == ) printf("%d\n", seg.query(, , n, l, r));
else
{
scanf("%d", &x);
if (op == ) seg.updateA(, , n, l, r, x);
else seg.updateO(, , n, l, r, x);
}
}
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}

BZOJ 5312: 冒险的更多相关文章

  1. 【刷题】BZOJ 5312 冒险

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

  2. BZOJ.5312.冒险(线段树)

    题目链接 \(Description\) 维护一个序列,支持区间and/or一个数.区间查询最大值. \(Solution\) 维护区间最大值?好像没什么用,修改的时候和暴力差不多. 我们发现有时候区 ...

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

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

  4. BZOJ5312:冒险——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5312 Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护 ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. 第一百六十节,封装库--JavaScript,ajax注册表单到数据库

    封装库--JavaScript,ajax注册表单到数据库 效果图 前台js var biaodan = $().xu_lie_biao_dan($('form').sh_jd()); //序列化获取表 ...

  2. db2 设置表 not null

    db2将原表列notnull属性修改为null属性的方法   今天把自己遇到的一个小问题跟大家分享一下如何修改db2数据库表中列的属性--将列的非空属性改为允许空的属性,修改数据表的某一列属性其实很简 ...

  3. 转载 web前端简历

    Web前端程序员简历模板 本简历模板由国内首家互联网人才拍卖网站「 JobDeer.com 」提供. (括号里的是我们的顾问编写的说明,建议在简历书写完成后统一删除) 先讲讲怎样才是一份好的技术简历 ...

  4. 我如何让echarts实现了分组(原创插件echarts.group代码分享)

    前言 echarts是百度出品的一款很棒的前端图表控件,被评为“百度少有的良心产品”.可以实现散点图.折线图.柱状图.地图.饼图.雷达图.K线图等等几十种常用.不常用的图表,效果酷炫. 示例地址:ht ...

  5. Duilib教程-控件练习

    一.控件消息的响应. 在HelloDuilib例子中,程序不能退出,在这里,我将添加一个关闭按钮,当点击它时,调用PostQuitMessage进行退出. 首先在界面的右上角添加一个关闭按钮,并取名为 ...

  6. 面试题思考:IO 和 NIO的区别,NIO优点

    面试时答: IO是面向流的,NIO是面向缓冲区的 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方: NIO则能前后移动流中的数据,因为是面向缓冲区的 ...

  7. Django - 请求与响应、表单、中间件、上下文处理器

    请求与响应篇 一.HttpRequest对象 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象.视图函数的第一个参数(request)是HttpRequest对象在djang ...

  8. HDU3308(LCIS) 线段树好题

    题目链接:传送门 题目大意:给你n个数,m个操作.操作有两种:1.U x y 将数组第x位变为y   2. Q x y 问数组第x位到第y位连续最长子序列的长度.对于每次询问,输出一个答案 题目思路: ...

  9. python中的 try...except...finally 的用法

    python中的 try...except...finally 的用法 author:headsen chen date:2018-04-09  16:22:11 try, except, final ...

  10. 【BZOJ3714】[PA2014]Kuglarz 最小生成树

    [BZOJ3714][PA2014]Kuglarz Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获 ...