COGS-2638 区间与,异或,询问max
本篇题解参考了这个博客
我们利用线段树来维护区间第最大值,考虑如何修改
每一次进行与操作时只有z的二进制为0的位会产生影响
每一次进行或操作时只有z的二进制为1的位会产生影响
所以只要该区间二进制相同的位刚好是z会产生影响的二进制为位
那么该修改对这个区间的影响是一样的,我们就可以用一个区间修改的标记进行维护
标记下传也很简单
现在的问题是如何快速合并两个区间
我们用0表示该区间第k位二进制位不同,1表示相同
显然可以用一个int来存下
左右区间相同的二进制位一定是左边区间相同的和右边区间相同的二进制位的交集的子集
显然 same[l]&same[r]就是交集 但是我们还要判断第k位在左右区间究竟是否相同
有可能左边第k位都是0,右边第k位全是1
我们只要左右区间各取一个代表元素,然后将这两个代表元素的相同位取出来与一下(same[l] & same[r])就好了
复杂度度大概是nlogn
# include<cstdio>
# include<algorithm>
# include<cstdlib>
# include<ctime>
# include<iostream>
using namespace std;
const int mn = ;
int a[mn];
struct segment{
int mx[mn*],sam[mn*],tag[mn*];
int bas;
void updown(int cur)
{
mx[cur]=max(mx[cur<<],mx[cur<<|]);
sam[cur]=((sam[cur<<] & sam[cur<<|]) & (~(mx[cur<<] ^ mx[cur<<|])));
}
void pushdown(int cur)
{
if(tag[cur])
{
mx[cur<<]+=tag[cur];
mx[cur<<|]+=tag[cur];
tag[cur<<]+=tag[cur];
tag[cur<<|]+=tag[cur];
tag[cur]=;
}
}
void build(int l,int r,int cur)
{
if(l==r)
{
mx[cur]=a[l];
sam[cur]=bas;
return ;
}
int mid=l+r>>;
build(l,mid,cur<<);
build(mid+,r,cur<<|);
updown(cur);
}
bool check(int cur,int val)
{
int tmp=(val ^ bas);
return (tmp & sam[cur])==tmp;
}
void update1(int l,int r,int cur,int L,int R,int z)
{
if(l>R || r<L) return ;
if(l>=L && r<=R && check(cur,z)) {
int tmp = (mx[cur] & z) - mx[cur];
tag[cur]+=tmp; mx[cur]+=tmp;
return ;
}
int mid=l+r>>;
pushdown(cur);
update1(l,mid,cur<<,L,R,z);
update1(mid+,r,cur<<|,L,R,z);
updown(cur);
}
void update2(int l,int r,int cur,int L,int R,int z)
{
if(l>R || r<L) return ;
if(l>=L && r<=R && ((z& sam[cur]) ==z)) {
int tmp = (mx[cur] | z) - mx[cur];
tag[cur]+=tmp; mx[cur] +=tmp;
return ;
}
int mid=l+r>>;
pushdown(cur);
update2(l,mid,cur<<,L,R,z);
update2(mid+,r,cur<<|,L,R,z);
updown(cur);
}
int query(int l,int r,int cur,int L,int R)
{
if(l>=L && r<=R) return mx[cur];
if(l>R || r<L) return ;
int mid=l+r>>;
pushdown(cur);
int ret=;
ret=max(query(l,mid,cur<<,L,R),query(mid+,r,cur<<|,L,R));
updown(cur);
return ret;
}
}T;
int n,m;
int main()
{
int opt,x,y,z;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
T.bas=;
T.build(,n,);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&opt,&x,&y);
if(opt==)
{
scanf("%d",&z);
T.update1(,n,,x,y,z);
}
else if(opt==)
{
scanf("%d",&z);
T.update2(,n,,x,y,z);
}
else printf("%d\n",T.query(,n,,x,y));
}
return ;
}
COGS-2638 区间与,异或,询问max的更多相关文章
- COGS 2638. 数列操作ψ 线段树
传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次an ...
- [HDU] 5306 Gorgeous Sequence [区间取min&求和&求max]
题解: 线段树维护区间取min求和求max 维护最小值以及个数,次小值 标记清除时,分情况讨论 当lazy>max1 退出 当max1>lazy>max2(注意不要有等号) 更新 否 ...
- 51Nod XOR key —— 区间最大异或值 可持久化字典树
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1295 1295 XOR key 题目来源: HackerRa ...
- 51Nod - 1295:XOR key (可持久化Trie求区间最大异或)
给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R).求ALL 至 ARR 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值 ...
- Wannafly Winter Camp 2020 Day 6H 异或询问 - 二分
给定一个长 \(n\) 的序列 \(a_1,\dots,a_n\),定义 \(f(x)\) 为有多少个 \(a_i \leq x\) 有 \(q\) 次询问,每次给定 \(l,r,x\),求 \(\s ...
- Atcoder Regular 098 区间Pre=Xor Q询问区间连续K去最小值最小极差
C 用scanf("%s")就会WA..不知道为什么 /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset ...
- 询问任意区间的min,max,gcd,lcm,sum,xor,or,and
给我们n个数,然后有m个询问,每个询问为L,R,询问区间[L,R]的最大最小值,最小公约数,最大公约数,和,异或,或,且 这些问题通通可以用RMQ的思想来解决. 以下用xor来作为例子 设dp[i][ ...
- 【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和
题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是 ...
- Atcoder Beginner Contest 121 D - XOR World(区间异或和)
题目链接:https://atcoder.jp/contests/abc121/tasks/abc121_d 题目很裸(Atcoder好像都比较裸 就给一个区间求异或和 n到1e12 肯定不能O(n) ...
随机推荐
- 威胁快报|ProtonMiner挖矿蠕虫扩大攻击面,加速传播
背景 近日,阿里云安全监测到一种挖矿蠕虫,正在互联网上加速传播.阿里云安全根据它使用ProtonMail邮箱地址作为矿池用户名的行为,将其命名为ProtonMiner.据分析,这种蠕虫与TrendMi ...
- TZ_14_Zuul网关
1.spring-cloud的微服务大致是 2.zuul是 Netflix开源的微服务网关, 它可以和 Eureka. Ribbon. Hystrix等组件配合使用.zul的核心是一系列的过滤器,这些 ...
- 前端(jQuery)(5)-- jQuery AJAX异步访问和加载片段
异步访问 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset ...
- 【JZOJ5233】【GDOI模拟8.5】概率博弈 树形dp+期望
题面 小A和小B在玩游戏.这个游戏是这样的: 有一棵n个点的以1为根的有根树,叶子有权值.假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列. 一开始在1号点有一颗棋子.两人轮流 ...
- 再问你Java内存模型的时候别再给我讲堆栈方法区
在介绍Java内存模型之前,先来看一下到底什么是计算机内存模型,然后再来看Java内存模型在计算机内存模型的基础上做了哪些事情.要说计算机的内存模型,就要说一下一段古老的历史,看一下为什么要有内存模型 ...
- 2019.9.19 csp-s模拟测试47 反思总结
思路接近正解?都想到了?这都是借口呀. 没有用的,往前走吧. T1:Emotional Flutter 我的做法和题解不太一样,我把s放在最后考虑了. 因为出发以后步幅是一样的,所以每一个黑条可以ba ...
- day37 04-Hibernate二级缓存:list和iterate方法比较
get()和load()方法既可以向一级缓存区放数据,也可以向二级缓存区放数据.这是查询一个的情况.要是查询所有呢?注意, // 查询所有.Query接口的list()方法. // list()方法会 ...
- 洛谷 P1951 收费站_NOI导刊2009提高(2) 最短路+二分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1951 收费站_NOI导刊2009提高(2) 其 ...
- MaxCompute Spark开发指南
0. 概述 本文档面向需要使用MaxCompute Spark进行开发的用户使用.本指南主要适用于具备有Spark开发经验的开发人员. MaxCompute Spark是MaxCompute提供的兼容 ...
- C++学习笔记----4.4 继承情况下的类作用域嵌套
引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好像这些成员 ...