传送门 : COGS 2638. 数列操作ψ 线段树

这道题让我们维护区间最大值,以及维护区间and,or一个数

我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ

由于发现若干次and,or之后,如果数据分布均匀,那么几乎所有的数在若干次操作后都会变成同一个数

因为我们的and操作中的0位,以及or操作当中的1位,都是可以把整个区间的那一二进制位重置为相同的

我们考虑利用这一个性质

如果我们直接维护一个区间内的值是否是相同的,那么效果会差很多。

我们发现我们在进行and操作的时候只有为0的二进制位才可能更改原本的二进制位

同样的,在进行or操作的时候也只有为1的二进制位才可能更改原本的二进制位

所以我们可以在区间内所有的数的对应的会做出修改的二进制位完全相同时作出区间整体修改

至于区间整体修改,我们很容易发现,实际上就是区间内加上一个数

所以对于每一个线段树节点,维护一个sam值,表示这个线段树代表的区间内二进制位的相同情况

对应二进制位为1,则代表区间内所有值的这一位都是相同的

随后我们通过对区间内所有元素对应二进制位是否相同的情况来判断是否可以进行区间修改即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline void read(int &x){
x=0;static char ch;static bool flag;flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);++i)
const int maxn = 100010;
const int bas = 0x7fffffff;
int T[maxn<<2],lazy[maxn<<2],sam[maxn<<2];
int a[maxn];
inline void update(int rt){
T[rt] = max(T[rt<<1],T[rt<<1|1]);
sam[rt] = (sam[rt<<1]&sam[rt<<1|1]) & (~(T[rt<<1]^T[rt<<1|1]));
}
inline void pushdown(int rt){
if(lazy[rt] == 0) return ;
T[rt<<1] += lazy[rt];lazy[rt<<1] += lazy[rt];
T[rt<<1|1] += lazy[rt];lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
void build(int rt,int l,int r){
if(l == r){
T[rt] = a[l];
sam[rt] = bas;
return ;
}int mid = l+r >> 1;
build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
update(rt);
}
int L,R,val,tmp;
inline bool check_a(int rt){
tmp = (val^bas);
return (tmp & sam[rt]) == tmp;
}
void modify_a(int rt,int l,int r){
if(L <= l && r <= R && check_a(rt)){
tmp = (T[rt] & val) - T[rt];
lazy[rt] += tmp;T[rt] += tmp;
return ;
}int mid = l+r >> 1;pushdown(rt);
if(L <= mid) modify_a(rt<<1,l,mid);
if(R > mid) modify_a(rt<<1|1,mid+1,r);
update(rt);
}
void modify_o(int rt,int l,int r){
if(L <= l && r <= R && (sam[rt] & val) == val){
tmp = (T[rt] | val) - T[rt];
lazy[rt] += tmp;T[rt] += tmp;
return ;
}int mid = l+r >> 1;pushdown(rt);
if(L <= mid) modify_o(rt<<1,l,mid);
if(R > mid) modify_o(rt<<1|1,mid+1,r);
update(rt);
}
int query(int rt,int l,int r){
if(L <= l && r <= R) return T[rt];
int mid = l+r >> 1;pushdown(rt);
if(R <= mid) return query(rt<<1,l,mid);
if(L > mid) return query(rt<<1|1,mid+1,r);
return max(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
}
int main(){
//freopen("series_wei.in","r",stdin);
//freopen("series_wei.out","w",stdout);
int n,m;read(n);read(m);
rep(i,1,n) read(a[i]);
build(1,1,n);int opt;
int cnt = 0 ;
while(m--){
read(opt);read(L);read(R);
if(opt == 1) read(val),modify_a(1,1,n);
else if(opt == 2) read(val),modify_o(1,1,n);
else printf("%d\n",query(1,1,n));
}
return 0;
}

COGS 2638. 数列操作ψ 线段树的更多相关文章

  1. 【COGS-2638】数列操作ψ 线段树

    题目链接: http://cogs.pro/cogs/problem/problem.php?pid=2638 Solution 用jry推荐的写法即可做到单次$O(log^{2}N)$,不过随机数据 ...

  2. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  3. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  4. cogs 264. 数列操作 单点修改 区间查询

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pyNimmVeq 264. 数列操作 ★☆   输入文件:shulie.in   输出文件:shu ...

  5. 洛谷P1438 无聊的数列 [zkw线段树]

    题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...

  6. 【bzoj4636】蒟蒻的数列 离散化+线段树

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801379.html 题目描述 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个 ...

  7. [bzoj4636]蒟蒻的数列_线段树

    蒟蒻的数列 bzoj-4636 题目大意:给定一个序列,初始均为0.n次操作:每次讲一段区间中小于k的数都变成k.操作的最后询问全局和. 注释:$1\le n\le 4\cdot 10^4$. 想法: ...

  8. cogs 1317. 数列操作C 区间修改 区间查询

    1317. 数列操作C ★★★   输入文件:shuliec.in   输出文件:shuliec.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述] 假设有一个长度为 n( ...

  9. cogs 1316. 数列操作B 区间修改 单点查询

    1316. 数列操作B ★★   输入文件:shulieb.in   输出文件:shulieb.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 假设有一个大小为 n(n ...

随机推荐

  1. vue项目配置less预编译语言

    当所有东西都 准备好之后 : 第一步: 安装less依赖,npm install less less-loader --save 第二步:找到webpack配置文件webpack.base.conf. ...

  2. 20145219 《Java程序设计》实验一 Java开发环境的熟悉(Linux + Eclipse)实验报告

    20145219 <Java程序设计>实验一 Java开发环境的熟悉(Windws + IDEA)实验报告 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA 编辑. ...

  3. C++/VC中ANSI与UNICODE中字符定义和函数对照表

    这样查起来方便多了 ANSI UNICODE 通用 说明 数据类型 (char.h) (wchar.h) (tchar.h)   char wchar_t TCHAR   char * wchar_t ...

  4. nagios无法载入静态资源

    使用nginx+nagios无法载入静态资源,看了下url中增加了一个/nagios 查看是/usr/local/nagios/etc/cgi.conf中url_html_path=/nagios 将 ...

  5. Android的四种储存方式(SQLite、FileSystem、SDCardSystem、SharedPreferences)

    主要记录一下安卓中几种常用的存储方式的用法. 一.SQLite 1.创建SQLiteOpenHelper对象(当然SQLiteOpenHelper是抽象类,不能直接创建): 2.通过上面创建的对象调用 ...

  6. strcpy的实现

    // // Strcpy.c // libin // // Created by 李宾 on 15/8/20. // Copyright (c) 2015年 李宾. All rights reserv ...

  7. Flume-NG源码阅读之FileChannel

    FileChannel是flume一个非常重要的channel组件,非常常用.这个channel非常复杂,涉及的文件更多涉及三个包:org.apache.flume.channel.file.org. ...

  8. java 处理emoji表情信息转换为String

    2种方式实现: 注意:如果发现运行时java.lang.NoClassDefFoundError:异常就是缺少了jar包.添加对应的jar包就可以. 一.emoji-java-4.0.0.jar实现 ...

  9. 全国城市部分js

    var areaJson22 = { "id": "0", "name": "全国", "parentId&q ...

  10. 四十三 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

    1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字段的类型以及相关属性elasticsearch会根据json源数据的基础类型猜测你想要的字段映射,将输入的数据转换成可搜索的索引项, ...