【COGS-2638】数列操作ψ 线段树
题目链接:
http://cogs.pro/cogs/problem/problem.php?pid=2638
Solution
用jry推荐的写法即可做到单次$O(log^{2}N)$,不过随机数据下表现非常优秀。
$log^{2}$大概就是一共$log$位,然后每位$O(N)$级的,所以一共$NlogN$段,每段在线段树上又是$log$。
jls给的详细证明就是说,每位单独考虑形成一个01串,势能函数就是每位差分后的$1$的个数,太详细的啥我也不是很熟练了..要是有路过的大神能详细讲一下咩QwQ
具体的就是维护一个区间的$same$,其二进制下01的意义表示区间中所有数的二进制位第$k$位是否相同。
处理标记,当整个区间的 需要修改 的二进制位相同时即可直接打上标记。
然后就是正常搞了啊..其实当满足上述的情况后修改就可以变成区间加减标记来处理了,只需要一个标记即可,常数会更优一点。
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} #define MAXN 100010 int N,M,a[MAXN]; #define AllSame ((1<<30)-1) struct SgtNode{
int l,r,otag,atag,same,maxx;
}tree[MAXN<<2]; inline void Update(const int &now)
{
tree[now].maxx=max(tree[now<<1].maxx,tree[now<<1|1].maxx);
tree[now].same=( tree[now<<1].same & tree[now<<1|1].same ) & ( tree[now<<1].maxx ^ (~tree[now<<1|1].maxx) );
} inline void Build(const int &now,const int &l,const int &r)
{
tree[now].l=l; tree[now].r=r;
tree[now].otag=0; tree[now].atag=AllSame;
if (l==r) {
tree[now].maxx=a[l]; tree[now].same=AllSame;
return;
}
int mid=(l+r)>>1;
Build(now<<1,l,mid); Build(now<<1|1,mid+1,r);
Update(now);
} inline void And(const int &now,const int &val) {tree[now].maxx&=val; tree[now].otag&=val; tree[now].atag&=val;} inline void Or(const int &now,const int &val) {tree[now].maxx|=val; tree[now].otag|=val; tree[now].atag|=val;} inline void Pushdown(const int &now)
{
if (tree[now].l==tree[now].r || (!tree[now].otag && tree[now].atag==AllSame)) return;
int ot=tree[now].otag,at=tree[now].atag;
tree[now].otag=0; tree[now].atag=AllSame;
if (ot) Or(now<<1,ot),Or(now<<1|1,ot);
if (at!=AllSame) And(now<<1,at),And(now<<1|1,at);
} inline bool CheckOr(const int &same,const int &val) {return (same&val)==val;} inline void ModifyOr(const int &now,const int &L,const int &R,const int &val)
{
int l=tree[now].l,r=tree[now].r;
if (L>r || R<l) return;
if (L<=l && R>=r && CheckOr(tree[now].same,val)) {
Or(now,val);
return;
}
Pushdown(now);
ModifyOr(now<<1,L,R,val);
ModifyOr(now<<1|1,L,R,val);
Update(now);
} inline bool CheckAnd(const int &same,const int &val) {return (~same&AllSame|val)==val;} inline void ModifyAnd(const int &now,const int &L,const int &R,const int &val)
{
int l=tree[now].l,r=tree[now].r;
if (L>r || R<l) return;
if (L<=l && R>=r && CheckAnd(tree[now].same,val)) {
And(now,val);
return;
}
Pushdown(now);
ModifyAnd(now<<1,L,R,val);
ModifyAnd(now<<1|1,L,R,val);
Update(now);
} inline int Query(const int &now,const int &L,const int &R)
{
int l=tree[now].l,r=tree[now].r;
if (L<=l && R>=r) {
return tree[now].maxx;
}
Pushdown(now);
int mid=(l+r)>>1,re=0;
if (L<=mid) re=Query(now<<1,L,R);
if (R>mid) re=max(re,Query(now<<1|1,L,R));
return re;
} int main()
{
freopen("series_wei.in","r",stdin);
freopen("series_wei.out","w",stdout); N=read(),M=read();
for (int i=1; i<=N; i++) a[i]=read();
Build(1,1,N);
while (M--) {
int opt=read(),l=read(),r=read(),val;
switch (opt) {
case 1: val=read(); ModifyAnd(1,l,r,val); break;
case 2: val=read(); ModifyOr(1,l,r,val); break;
case 3: printf("%d\n",Query(1,l,r)); break;
}
}
return 0;
}
/*
8 6
4 0 5 7 2 9 12 8
2 2 5 15
1 3 5 2
3 5 7
1 5 7 12
2 1 6 4
3 2 6
*/
【COGS-2638】数列操作ψ 线段树的更多相关文章
- COGS 2638. 数列操作ψ 线段树
传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次an ...
- BZOJ_4636_蒟蒻的数列_线段树+动态开点
BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- cogs 264. 数列操作 单点修改 区间查询
http://cogs.pro:8080/cogs/problem/problem.php?pid=pyNimmVeq 264. 数列操作 ★☆ 输入文件:shulie.in 输出文件:shu ...
- 洛谷P1438 无聊的数列 [zkw线段树]
题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...
- 【bzoj4636】蒟蒻的数列 离散化+线段树
原文地址:http://www.cnblogs.com/GXZlegend/p/6801379.html 题目描述 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个 ...
- [bzoj4636]蒟蒻的数列_线段树
蒟蒻的数列 bzoj-4636 题目大意:给定一个序列,初始均为0.n次操作:每次讲一段区间中小于k的数都变成k.操作的最后询问全局和. 注释:$1\le n\le 4\cdot 10^4$. 想法: ...
- cogs 1317. 数列操作C 区间修改 区间查询
1317. 数列操作C ★★★ 输入文件:shuliec.in 输出文件:shuliec.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述] 假设有一个长度为 n( ...
- cogs 1316. 数列操作B 区间修改 单点查询
1316. 数列操作B ★★ 输入文件:shulieb.in 输出文件:shulieb.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 假设有一个大小为 n(n ...
随机推荐
- bzoj千题计划185:bzoj1260: [CQOI2007]涂色paint
http://www.lydsy.com/JudgeOnline/problem.php?id=1260 区间DP模型 dp[l][r] 表示涂完区间[l,r]所需的最少次数 从小到大们枚举区间[l, ...
- Ubuntu 16.04开机自启Nginx简单脚本
本文要记述的是最简单的Ubuntu下开机自启 nginx的脚本 这里将nginx装在了/usr/local/nginx目录下,nginx本身没有注册成服务,所以直接使用服务开机自启是不行的,除非自己写 ...
- ASP.Net巧用窗体母版页
背景:每个网页的基本框架结构类似: 浏览网站的时候会发现,好多网站中,每个网页的基本框架都是一样的,比如,最上面都是网站的标题,中间是内容,最下面是网站的版权.开发提供商等信息: 在这些网页中,表头. ...
- 【BZOJ】1095: [ZJOI2007]Hide 捉迷藏 括号序列+线段树
[题目]BZOJ 1095 [题意]给定n个黑白点的树,初始全为黑点,Q次操作翻转一个点的颜色,或询问最远的两个黑点的距离,\(n \leq 10^5,Q \leq 5*10^5\). [算法]括号序 ...
- iOS 6 & iOS 7 的适配笔记
iOS 6 & iOS 7 的适配 场景1: 没有NavigationController,同时根视图是UIView- (void)viewWillLayoutSubviews{ if ([[ ...
- Linux - ssh 连接问题
SSH 连接方式 ssh -p 22 user@192.168.1.209 # 从linux ssh登录另一台linux ssh -p 22 root@192.168.1.209 CMD # 利用ss ...
- 将本地的mongodb迁移到阿里云
首先在阿里云上安装mongodb,可以根据官方教程 https://docs.mongodb.com/manual/tutorial/install-mongodb-on-amazon/ 完成之后启动 ...
- Linux awk工具简单学习记录
awk是一个文本分析工具,它把文件逐行读入,以特定符号将每行切分(默认空格为分隔符),切开的部分再进行各种分析处理. awk其名称得自于它的创始人Alfred Aho .Peter Weinberge ...
- Hibernate二级缓存(未完待续)
1.Hibernate的cache介绍: Hibernate实现了良好的Cache机制,可以借助Hibernate内部的Cache迅速提高系统的数据读取性能.Hibernate中的Cache可分为两层 ...
- SPListItem.UpdateOverwriteVersion()真的不会创建新版本吗?
根据msdn文档, SPListItem.UpdateOverwriteVersion(): Updates the item without creating another version of ...