题目大意:

给定一个序列,每次单点修改一个数,或给定$x$,询问最短的or起来大于等于$x$的区间的长度(不存在输出-1)。

解题思路:

在太阳西斜的这个世界里,置身天上之森。等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去、逐渐消逝的未来。我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘。————世界上最幸福的女孩

盼你归来,珂朵莉~

---

这些题目果然一道比一道神仙

众所周知,这道题分块。

然后你就珂以去看shadowice1984的题解了

好吧窝来复述一下吧(雾)

首先有一个结论,对于一个区间,如果其中一个端点固定,则区间or和的不同取值最多$\log a$个,因为or和是按位变大的(不会变小)。

先假设我们手里有一个已经分好块的序列,块大小为$S$,那么对于询问,就有两种情况:区间在一个块内,区间跨了几个块。

考虑处理出每个块内,长度为$len$的区间的最大异或和。然后对于区间在块内的情况,直接二分即可。单次询问复杂度$O(\frac{n\log S}{S})$。

由于有单点修改操作,我们还要考虑快速修改这个数组。根据刚刚说的结论,对每个点作端点,不同or和最多$\log a$个,所以处理出每个数的每一位在之后(包括自己)第一次出现的位置,然后按顺序or即可。

还有个问题,我们需要“按顺序”or,排序的话就会多一个$\log\log a$。

假设我们已经知道位置$i$要or的那些位置的顺序构成的队列,对于位置$i-1$,先把它出现过的位塞进队列,再从前往后扫描位置$i$的队列,把没出现在位置$i-1$的位塞进队列。这个队列就是第$i-1$位要转移的位置的顺序。单次复杂度$O(S\log a)$。

现在考虑跨块的区间。我们从左往右枚举块,处理以第$i$个块的块尾结尾的后缀的不同or和(同时记录位置)。

然后考虑第$i+1$个块的所有不同前缀,用双指针扫描后缀和前缀(左端点往右,右端点也往右),更新答案即可。

接着考虑如何从第$i$块的后缀转移到第$i+1$块的贡献。先把原来的后缀or上第$i+1$块所有数的or和,然后用归并排序把第$i+1$块的后缀并上去即可。最后去重,出现多次的保留最后出现的即可。

复杂度$O(\frac{n\log a}{S})$。

$S$取$\sqrt n$,得总复杂度$O(n\sqrt n\log n)$。

然后卡卡常数。

C++ Code:

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<cstdio>
#include<cctype>
#include<utility>
#include<algorithm>
#include<cstring>
char buf[8888888],*it;
void init(){fread(it=buf,1,8888886,stdin);fclose(stdin);}
inline int readint(){int d=0;for(;!isdigit(*it);++it);while(isdigit(*it))d=d*10+(*it++^'0');return d;
}
#define mp std::make_pair
#define bel(x)((x-1)/siz+1)
typedef std::pair<int,int>PII;
inline bool operator<(const PII&a,const PII&b){return(a.first!=b.first)?a.first<b.first:a.second>b.second;
}
const int siz=400;
int a[60000];
inline void chkmax(int&a,const int&b){if(a<b)a=b;}
inline void chkmin(int&a,const int&b){if(a>b)a=b;}
int ans,pv;
PII q[23333],vec[66],c[66];
struct BLOCK{int mx[402],val[402],L,R,cntp,cnts,all;PII pre[33],suf[33];void re(){memset(mx,0,sizeof mx);for(int i=1,p=cntp=0;i<=siz;++i)if((p|=val[i])!=pre[cntp].first)pre[++cntp]=mp(p,i+L-1);for(int i=siz,p=cnts=0;i;--i)if((p|=val[i])!=suf[cnts].first)suf[++cnts]=mp(p,i+L-1);int head=1,tail=0;for(int i=siz;i;--i){const int lst=tail,v=val[i];for(int j=v;j;j^=j&-j)q[++tail]=mp(__builtin_ctz(j),i);for(int j=head;j<=lst;++j)if(!(v>>q[j].first&1))q[++tail]=q[j];head=lst+1;for(int j=head,now=0;j<=tail;++j){const int pos=q[j].second;chkmax(mx[pos-i+1],now|=val[pos]);}}for(int i=2;i<=siz;++i)chkmax(mx[i],mx[i-1]);all=pre[cntp].first;}void build(int l,int r){L=l,R=r;for(int i=l;i<=r;++i)val[i-l+1]=a[i];re();}void modify(int pos,int v){val[pos-L+1]=v;re();}inline int getlen(int v){return std::lower_bound(mx+1,mx+siz+1,v)-mx;}inline void merge_suffix_to_vec(){int l=1,r=1,it=1;while(l<=pv&&r<=cnts)c[it++]=(vec[l]<suf[r])?vec[l++]:suf[r++];while(l<=pv)c[it++]=vec[l++];while(r<=cnts)c[it++]=suf[r++];vec[1]=c[1];for(int i=2;i<it;++i){vec[i]=c[i];if(vec[i].first==vec[i-1].first)vec[i].second=vec[i-1].second;}pv=std::unique(vec+1,vec+it)-vec-1;}inline void check_prefix_with_vec(const int&v){int len=233333;for(int i=1;i<=cntp;++i)while(pv&&(vec[pv].first|pre[i].first)>=v)chkmin(len,pre[i].second-vec[pv--].second+1);chkmin(ans,len);}
}b[130];
int n,m,K;
int main(){init();n=readint(),m=readint();for(int i=1;i<=n;++i)a[i]=readint();n=bel(n)*siz;K=n/siz;for(int i=1;i<=K;++i)b[i].build((i-1)*siz+1,i*siz);while(m--)if(readint()==1){const int pos=readint(),x=readint();b[bel(pos)].modify(pos,x);a[pos]=x;}else{ans=233333;const int x=readint();for(int i=1;i<=K;++i)if(b[i].all>=x)chkmin(ans,b[i].getlen(x));pv=0;b[1].merge_suffix_to_vec();for(int i=2;i<=K;++i){b[i].check_prefix_with_vec(x);for(int j=1;j<=pv;++j)vec[j].first|=b[i].all;b[i].merge_suffix_to_vec();}printf("%d\n",(ans==233333)?-1:ans);}return 0;
}

转载于:https://www.cnblogs.com/Mrsrz/p/10391968.html

[Ynoi2014]不归之人与望眼欲穿的人们相关推荐

  1. 题解 P5065 【[Ynoi2014]不归之人与望眼欲穿的人们】

    出现了一篇跑得炒鸡慢的题解! noteskey 无 fuck 说,好像就是整个数列分块然后合并区间...什么的吧 对于每块内部就是算一下前缀信息.后缀信息(就是以 第一个点/最后一个点 为一个边界,不 ...

  2. 洛谷P5071 [YNOI2015]此时此刻的光辉 莫队+玄学优化+卡常QWQ

    题目链接:传送门 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到未来,此时此 ...

  3. 洛谷P3987 我永远喜欢珂朵莉~ 树状数组+vector(暴力)

    题目链接:我永远喜欢珂朵莉- 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到 ...

  4. 洛谷P5072 [YNOI2015]盼君勿忘 莫队+unordered_set+毒瘤卡常

    在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐渐消逝的未来.我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘 ...

  5. 平衡树(splay)学习笔记(详细,从入门到精(bao)通(ling))(持续更新)

    前言 在前几天军训站军姿的时候胡思乱想,突然明白了splay的本质 KMP学习笔记后又一篇字数上万的题解- 前置技能--二叉搜索树 首先来看一个最简单的问题: 你需要维护一个数据结构,资磁这些操作: ...

  6. [Ynoi2015]即便看不到未来

    题目大意: 给定一个序列,每次询问,给出一个区间$[l,r]$. 设将区间内的元素去重后重排的数组为$p$,求$p$中长度为$1\sim 10$的极长值域连续段个数. 长度为$L$的极长值域连续段的定 ...

  7. [Ynoi2015]纵使日薄西山

    题目大意: 给定一个序列,每次单点修改,然后进行询问. 定义一次操作为,选择一个位置$x$,将这个位置的数和左边.右边两个位置的数(不存在则忽略)各减去1,然后和0取max. 对序列中最大的位置进行一 ...

  8. CSP-J2021 第一轮(初赛)游记

    # CSP-J2021 第一轮(初赛)游记 ## 前言 本次 CSP 已经是本蒟蒻的第三个赛季了.(**坐标:山东济南**) 首先回顾一下前两个赛季: $2019$:CSP-X 二等奖[小学组],当时 ...

  9. 浅谈珂朵莉树(ODT)

    前言 珂学家狂喜( 文章目录 前言 一.珂朵莉树来源 二.珂朵莉树 1.珂朵莉树有什么用? 2.原理是什么? a.存储 b.分割结点 c.推平 d.剩余操作 3.复杂度分析 三.珂朵莉树例题 1.P4 ...

  10. 硬核科普:到底啥是云原生?

    本文主要根据课程 什么是云原生?_哔哩哔哩_bilibili 总结而来,其他参考文章如下: <云原生人才计划之Kubernetes 技术图谱>发布! - 知乎 (zhihu.com) ku ...

最新文章

  1. Java Graphics类的绘图方法
  2. 单词接龙pascal程序
  3. 什么时候你应该用JSON Web Token
  4. Google准备开始新一年的大扩张
  5. (91)如何网表文件?
  6. Shiro(三)——Shiro授权入门案例
  7. pmp 第六版 模拟卷5错题整理
  8. 读书笔记2014第12本:《创新者的窘境》
  9. Scratch作品(一)
  10. Html5开发工具介绍
  11. renderdoc 抓google地图
  12. 《壁纸 - 大全精选手机壁纸》EULA条款协议
  13. JAVA经典兔子问题
  14. EXCEL快捷键大全(三)(九耶-钛伦特)
  15. 手把手教你绘制积分动图
  16. 基于hadoop平台hive数据库处理电影数据
  17. html emmet输入法_Emmet HTML参考
  18. 三菱FX系列DPLSY指令使用
  19. MySQL运行机制-从入门到京东
  20. python之字符编码、存取文件乱码问题、python2字符串乱码问题

热门文章

  1. MATLAB——网格图画法
  2. 【组队学习】【32期】组队学习内容详情
  3. Unity移动端、WebGL 四边形线框Shader 实现
  4. 实现商品库存信息管理页面
  5. 202109青少年软件编程(Python)等级考试(五级编程题)
  6. 智能视频监控 计算机视觉,传统视频监控与智能视频监控之对比
  7. NOIP 模拟题 国际跳棋
  8. 基于74hc573的数码管模块测试
  9. CPU飙高系统反应慢怎么排查?
  10. 零基础:21天搞定Python分布爬虫