传送门 : 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. 菜单Menu

    <Menu HorizontalAlignment="> <MenuItem Header="文件"> <MenuItem Header=& ...

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

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

  3. 关于Block汇总

    //使用总结: //1.当block里面会有b类相关的参数要回调回去的时候,属性用copy修饰,将其拷贝到堆里面,这样即便栈释放掉了,b类的指针也在堆中存在,能够成功的回调回去. //Block默认存 ...

  4. Flume-NG源码阅读之SinkGroups和SinkRunner

    在AbstractConfigurationProvider类中loadSinks方法会调用loadSinkGroups方法将所有的sink和sinkgroup放到了Map<String, Si ...

  5. ZC__问题

    1. int.long.float 等的类型 如何创建 Class对象? ZC: 不能创建的话,反射里面只能使用 Integer等的包装类 作为参数了? ZC: 查了一下,貌似 要用反射创建对象,就不 ...

  6. Nginx的长链接

    网站使用程序discuz3访问都正常,只有用户登录存在异常,具体就是:用户登陆后会马上显示未登录,然后刷新一下又变成了登录中 这个问题的原因显然是由于session导致,后台有多个web机器,当用户登 ...

  7. es6 中的let,const

    在es6中,let的作用和var差不多,都是用来声明变量的,但是他们之间的区别在于作用域不同,大家都知道在js中没有块级作用域,例如: for(var i=0;i<10;i++){ consol ...

  8. ie7 动态改变select option时,宽度自动变短解决方法

    <html> <head> <title>JQuery</title> <meta http-equiv="pragma" c ...

  9. sass基础篇

    scss的语法非常简单: $color: red; div{ color: $color; } 这就是一个简单的scss代码. 但是,使用 Sass 进行开发,那么是不是直接通过“<link&g ...

  10. shell基础复习笔记

    变量的设置 以等号连接,等号两边不能有空格 变量名首个字符必须是英文,可以使用下划线,不能使用标点符号,不能使用bash里的关键字 可以使用转义字符\将特殊符号(如Enter.$.空格.!等)变成一般 ...