题目大意:

给定一个序列,每次单点修改一个数,或给定$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;
}

[Ynoi2014]不归之人与望眼欲穿的人们的更多相关文章

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

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

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

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

  3. [Ynoi2015]纵使日薄西山

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

  4. [Ynoi2015]盼君勿忘

    题目大意: 给定一个序列,每次查询一个区间\([l,r]\)中所有子序列分别去重后的和\(\bmod p\)(每次询问模数不同). 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后 ...

  5. [Ynoi2015]我回来了

    题目大意: 给定一张无向无权图,每次给定若干个二元组\((x_i,y_i)\),定义点\(u\)满足条件,当且仅当存在\(i\),并满足\(dist(u,x_i)\leqslant y_i\)(\(d ...

  6. [Ynoi2015]此时此刻的光辉

    题目大意: 给定一个序列,每次询问一段区间的数的乘积的约数个数. 解题思路: 在太阳西斜的这个世界里,置身天上之森.等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去.逐 ...

  7. 不得不喷一下中控科技,ZKT,恶心的中控,售后技术和屎一样,半年不见人。

    要做一个指纹考勤机和后台通信写入到mysql.在淘宝看了好多款,于是决定用指纹考勤机w6.卖家当时说支持二次开发,给我发的sdk.于是买了一台测试.机器来了开始测试,使用发的demo不能使用,于是去中 ...

  8. GitHub 实现多人协同提交代码并且权限分组管理

    转载请标明出处: http://www.cnblogs.com/zhaoyanjun/p/5882784.html 出自[赵彦军博客] 2016-09-19 前言: 在上一篇文章中Android gi ...

  9. <转>请戒掉成功学和正能量,那是麻痹人的毒药 | 新知

    非常不幸的是,这将是一场非常糟糕的演说.我不想骗你们,你们从我这里几乎什么也学不到.你们在离开的时候肯定会感到失望,你们的生活并不会得到改善. 更糟糕的是,你还会意识到生活的本质毫无意义,你的一切努力 ...

随机推荐

  1. Uva 1331 - Minimax Triangulation(最优三角剖分 区间DP)

    题目大意:依照顺时针或者逆时针的顺序给出多边的点,要将这个多边形分解成n-2个三角形,要求使得这些三角行中面积最大的三角形面积尽量小,求最小值. 思路:用区间DP能够非常方便解决,多边形可能是凹边形, ...

  2. HDU 5347(MZL&#39;s chemistry-打表)

    MZL's chemistry Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  3. oracle中使用impdp数据泵导入数据提示“ORA-31684:对象类型已经存在”错误的解决

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/47448751 本文出自[我是干勾鱼的博客] oracle中使用impdp数据泵导 ...

  4. ExtJs 日期相加,Grid表格列可编辑

    1.日期相加: Ext.Date.add(new Date(), Ext.Date.DAY, 15) 2.Grid表格列可编辑: {    header : "实际已交货量",   ...

  5. SpringMVC + MyBatis 配置文件

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="htt ...

  6. luogu1312 Mayan游戏 剪枝

    题目大意 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个77 行\times 5×5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...

  7. 使用tortoisegit修改日志

    http://stackoverflow.com/questions/17647936/how-do-i-edit-an-incorrect-commit-message-with-tortoiseg ...

  8. C# textbox中输入时加限制条件 // C#Winform下限制TextBox只能输入数字 // 才疏学浅(TextBox 小数点不能在首位+只能输入数字)

    textbox中输入时加限制条件 分类: C# winform2008-08-26 08:30 306人阅读 评论(0) 收藏 举报 textbox正则表达式object 1.用正则表达式! 2.使用 ...

  9. Codeforces--630E--A rectangle(规律)

     E - A rectangle Crawling in process... Crawling failed Time Limit:500MS     Memory Limit:65536KB  ...

  10. PCB Genesis原点坐标转换关系

    一.Genesis原点坐标转换关系: 1.读取Genesis坐标转换:   UI界面坐标 = 文件坐标 - 偏移值 2.写入Genesis坐标转换:   文件坐标 = UI界面坐标 + 偏移值 3.为 ...