NOIP 模拟 $36\; \rm Cicada 拿衣服$
题解 \(by\;zj\varphi\)
发现右端点固定时,左端点的 \(min-max\) 单调递减,且对于 \(or\) 和 \(and\) 相减,最多有 \(\rm2logn\)个不同的值,且相同的值构成一段连续的区间。
那么就可以在最远的,符合答案的第一个区间二分答案。
具体实现可以用一个链表,每次扫一遍合并,并倒着查合法区间,这样就能做到 \(\rm nlogn\)。
Code
#include<bits/stdc++.h>
#define ri register signed
#define Re register
#define p(i) ++i
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
struct nanfeng_stream{
template<typename T>inline nanfeng_stream operator>>(T &x) {
ri f=0;x=0;register char ch=gc();
while(!isdigit(ch)) f|=ch=='-',ch=gc();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
return x=f?-x:x,*this;
}
}cin;
}
using IO::cin;
namespace nanfeng{
#define node(x,y,z) (node){x,y,z}
#define eb emplace_back
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
static const int N=1e6+7;
struct node{int l,OR,AND;int val() {return OR-AND;}};
std::list<node> lis;
int a[N],stn[N][23],stx[N][23],lg[N],n,k;
inline void init_rmq() {
for (ri i(1);i<=n;p(i)) stx[i][0]=stn[i][0]=a[i];
for (ri i(2);i<=n;p(i)) lg[i]=lg[i>>1]+1;
for (ri j(1);j<19;p(j)) {
ri len=1<<j;
for (ri i(1);i+len-1<=n;p(i)) {
stx[i][j]=cmax(stx[i][j-1],stx[i+(1<<j-1)][j-1]);
stn[i][j]=cmin(stn[i][j-1],stn[i+(1<<j-1)][j-1]);
}
}
}
inline int Getmx(int l,int r) {
int k=lg[r-l+1];
return cmax(stx[l][k],stx[r-(1<<k)+1][k]);
}
inline int Getmn(int l,int r) {
int k=lg[r-l+1];
return cmin(stn[l][k],stn[r-(1<<k)+1][k]);
}
inline bool check(Re std::list<node>::iterator it,int l,int r) {return it->val()+Getmn(l,r)-Getmx(l,r)>=k;}
struct Seg{
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
struct segmenttree{int mx,lz;segmenttree(){mx=lz=-1;}}T[N<<2];
inline void down(int x) {
int l=ls(x),r=rs(x);
T[l].mx=cmax(T[l].mx,T[x].lz);
T[r].mx=cmax(T[r].mx,T[x].lz);
T[l].lz=cmax(T[l].lz,T[x].lz);
T[r].lz=cmax(T[r].lz,T[x].lz);
}
void update(int x,int l,int r,int lt,int rt) {
if (l<=lt&&rt<=r) {
T[x].lz=cmax(T[x].lz,r-l+1);
T[x].mx=cmax(T[x].mx,r-l+1);
return;
}
down(x);
int mid(lt+rt>>1);
if (l<=mid) update(ls(x),l,r,lt,mid);
if (r>mid) update(rs(x),l,r,mid+1,rt);
}
void print(int x,int l,int r) {
if (l==r) return (void)(printf("%d ",T[x].mx));
int mid(l+r>>1);
down(x);
print(ls(x),l,mid);
print(rs(x),mid+1,r);
}
}T;
inline int main() {
//FI=freopen("nanfeng.in","r",stdin);
//FO=freopen("nanfeng.out","w",stdout);
cin >> n >> k;
for (ri i(1);i<=n;p(i)) cin >> a[i];
init_rmq();
for (ri i(1);i<=n;p(i)) {
for (Re auto it=lis.begin();it!=lis.end();p(it)) it->OR|=a[i],it->AND&=a[i];
lis.eb(node(i,a[i],a[i]));
for (Re auto it1=lis.begin(),it2=next(it1);it2!=lis.end();p(it2))
if (it1->val()==it2->val()) lis.erase(it1),it1=it2;
else p(it1);
for (Re auto it=lis.begin();it!=lis.end();p(it))
if (check(it,it->l,i)) {
ri l=1,r=it->l,res;
if (it!=lis.begin()) l=prev(it)->l+1;
while(l<=r) {
int mid(l+r>>1);
if (check(it,mid,i)) r=mid-1,res=mid;
else l=mid+1;
}
T.update(1,res,i,1,n);
break;
}
}
T.print(1,1,n);
return 0;
}
}
int main() {return nanfeng::main();}
NOIP 模拟 $36\; \rm Cicada 拿衣服$的更多相关文章
- NOIP 模拟 $36\; \rm Cicada 与排序$
题解 \(by\;zj\varphi\) 设 \(rk_{i,j}\) 表示第 \(i\) 个数最后在相同的数里排第 \(j\) 位的概率. 转移时用一个 \(dp\),\(dp_{i,j,0/1}\ ...
- NOIP 模拟 $36\; \rm Dove 打扑克$
题解 \(by\;zj\varphi\) 引理 对于一个和为 \(n\) 的数列,不同的数的个数最多为 \(\sqrt n\) 证明: 一个有 \(n\) 个不同的数的数列,和最小就是 \(n\) 的 ...
- 20190902+0903合集-NOIP模拟
一直没时间写QwQ 于是补一下. Day 1 晚饭吃的有点恶心…… $1s\,2s\,5s$ 还开 -O2 ?? 有点恐怖. T1 猛的一想: 把外面设成一个点, 向入口连一条权为排队时间的边 从出口 ...
- 2021.5.22 noip模拟1
这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...
- Noip模拟36 2021.8.11
刚题的习惯还是改不了,怎么办??? T1 Dove打扑克 考场上打的动态开点线段树+并查集,考后发现自己像一个傻子,并查集就行.. 这几天恶补数据结构疯了 用树状数组维护后缀和,$siz_i$表示编号 ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
- NOIP模拟
1.要选一个{1,2,...n}的子集使得假如a和b在所选集合里且(a+b)/2∈{1,2,...n}那么(a+b)/2也在所选集合里 f[i]=2*f[i-1]-f[i-2]+g[i] g[n]:选 ...
- NOIP模拟3
期望得分:30+90+100=220 实际得分:30+0+10=40 T1智障错误:n*m是n行m列,硬是做成了m行n列 T2智障错误:读入三个数写了两个%d T3智障错误:数值相同不代表是同一个数 ...
- 9.18[XJOI] NOIP训练36
***在休息了周末两天(好吧其实只有半天),又一次投入了学车的怀抱,重新窝在这个熟悉的机房 今日9.18(今天以后决定不写打卡了) 日常一日总结 一个昏昏欲睡的早晨 打了一套不知道是谁出的题目,空间限 ...
随机推荐
- XCTF(MISC) 图片隐写
题目描述:菜猫给了菜狗一张图,说图下面什么都没有 1.给了个pdf,打开是这玩意 2.盲猜flag是图片后面,右键直接删除图片试试. 答案出来了.
- buu crackRTF
一.无壳,拖入ida,静态编译一下 整体逻辑还是很清晰,这里我的盲区是那个加密函数,是md5,没看出来,内存地址看错了,之前用黑盒动调一下,发现猜不出来,看某位wp发现有的老哥,直接sha1爆破的,狠 ...
- asp.net mvc中的路由
[Route] 路由 [Route("~/")] 忽略路由前缀 [Route("person/{id:int}")] 路由内联约束 [Route("h ...
- PyCharm代码区不能编辑的解决办法
问题: 修改之前的Python代码时发现代码区无法编辑,无意中输入i后又可以编辑了. 解决: 原因是打开了工具中的vim Emulator编辑模式,把vim Emulator前面的勾取消即可.
- 剖析:如何用 SwiftUI 5天组装一个微信 —— 通讯录发现我篇
前置资源 GitHub: SwiftUI-WeChatDemo 第零章:用 SwiftUI 5天组装一个微信 第一章:剖析:如何用 SwiftUI 5天组装一个微信 -- 聊天界面篇 通讯录 通讯录的 ...
- CF1330B题解
题意: 给定一个长为 \(n\) 序列 \(a\) ,问是否能分成两个排列,并输出方案 (排列:从 \(1-n\) 中选取不同的 \(n\) 个元素组成的序列) 思路: 观察数据范围可以猜出,这题 \ ...
- 原来ReadWriteLock也能开发高性能缓存,看完我也能和面试官好好聊聊了!
大家好,我是冰河~~ 在实际工作中,有一种非常普遍的并发场景:那就是读多写少的场景.在这种场景下,为了优化程序的性能,我们经常使用缓存来提高应用的访问性能.因为缓存非常适合使用在读多写少的场景中.而在 ...
- 开发工具IDE从入门到爱不释手(一)项目初始配置
前言 版本:IDE 2019.2.3 JDK:1.8 一.字体 快捷键:Ctrl+Alt+S ;打开Settings,一般系统配置都在这里 输入font,需要修改字体有三处 Apperance:ID ...
- 13Java进阶——IO、线程
1 字节缓冲流 BufferInputStream 将创建一个内部的缓冲区数组,内部缓冲区数组将根据需要从包含的输入流中重新填充,一次可以读取多个字节 BufferOutputStream 该类实现缓 ...
- 微信小程序 -- scroll view
效果图:横向滚动和纵向滚动 scroll view使用方法文档,前面已经介绍查找文档方法,此处不再赘述 一.横向滚动 创建一个页面scroll-nav 然后,在.wxml文件中排版 <!--水平 ...