CF1936D. Bitwise Paradox-位运算、分治、线段树
link:https://codeforces.com/contest/1936/problem/D
题意:给两个长度为
- 1、
. - 2、给
,问 的所有好的子区间 ,美丽值最小的是多少?
分析性质:
- 1、如果某个区间
是好的,则更大的区间 ( ) 一定是好的,同时因为美丽值是max,因此一定会更大,而我们希望的是最小的美丽值,因此真正关心的是一个个极小的好区间。 - 2、对于
的位运算问题,可以改写成 ,然后拆位考虑,具体见3 - 3、对于区间的子区间问题,会想到最大子段和问题(同样是问区间的子区间):
的答案,要么来自于左半边,要么来自右半边,要么来自某个跨过中点的区间。前两个递归解决,考察最后一个情况:-
假设从中点向着两边扩展,我希望找到一些 或和
的区间,如果只看一个方向,首先要注意到一个性质(我场内就没注意到…)——按位或是单调不减的,而每次变大一定是某个二进制的 ,因此会让按位或变大的位置,只有 个。 -
从左到右和从右到左是类似的,因此我们考虑用线段树维护两个长度为31的数组
pre,suf
,表示区间从两个方向扩展,二进制的某一位为 的第一个位置,这个信息很好合并。 -
答案怎么更新?就是看拆位,我们想的时候举个栗子,比如要严格大于二进制数:
01011
,那么我可以是1xxxx
,011xx
,这样。也就是说我从高到低去看:一方面是b[]
的这位能不能凑出1
,另一方面是 的这一位是多少。
- 如果只能凑出0就没什么好说了,如果能凑出1,那我希望
尽量小,就要去比较左右两边用哪边的 1 更好,所以需要维护一个当前扩展出去的区间,以及涉及到一个静态RMQ,用st表处理。
核心代码:
- 如果只能凑出0就没什么好说了,如果能凑出1,那我希望
-
sgt operator +(const sgt &ls,const sgt &rs){ sgt ret; int L=ls.r;ret.l=ls.l; int R=rs.l;ret.r=rs.r; ret.v=min(ls.v,rs.v); for(int i=30;i>=0;i--){ ret.pre[i]=(ls.pre[i]?ls.pre[i]:rs.pre[i]); ret.suf[i]=(rs.suf[i]?rs.suf[i]:ls.suf[i]); } for(int i=30;i>=0;i--){ if(!ls.suf[i]&&!rs.pre[i]){ if(digit[i])break; continue; } int _L=min(L,ls.suf[i]),_R=max(R,rs.pre[i]); if(digit[i]){ if(!ls.suf[i])R=_R; else if(!rs.pre[i])L=_L; else{ if(st.query(_L,ls.r)<st.query(rs.l,_R))L=_L; else R=_R; } }else{ if(!ls.suf[i])ret.v=min(ret.v,st.query(L,_R)); else if(!rs.pre[i])ret.v=min(ret.v,st.query(_L,R)); else ret.v=min({ret.v,st.query(L,_R),st.query(_L,R)}); } } return ret; }
代码:
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define endl '\n' #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; const int N=2e5+5; const int INF=0x3f3f3f3f; int n,v,a[N],b[N]; bool digit[50]; struct ST{ int f[21][N]; void init(int *a,int n){ rep(i,1,n)f[0][i]=a[i]; for(int j=1;j<=20;j++)for(int i=1;i+(1<<j)-1<=n;i++) f[j][i]=max(f[j-1][i],f[j-1][i+(1<<(j-1))]); } int query(int l,int r){ int k=__lg(r-l+1); return max(f[k][l],f[k][r+1-(1<<k)]); } }st; struct sgt{ int suf[31],pre[31]; int v,l,r; sgt(){ memset(suf,0,sizeof(suf)); memset(pre,0,sizeof(pre)); v=INF; } }; sgt operator +(const sgt &ls,const sgt &rs){ sgt ret; int L=ls.r;ret.l=ls.l; int R=rs.l;ret.r=rs.r; ret.v=min(ls.v,rs.v); for(int i=30;i>=0;i--){ ret.pre[i]=(ls.pre[i]?ls.pre[i]:rs.pre[i]); ret.suf[i]=(rs.suf[i]?rs.suf[i]:ls.suf[i]); } for(int i=30;i>=0;i--){ if(!ls.suf[i]&&!rs.pre[i]){ if(digit[i])break; continue; } int _L=min(L,ls.suf[i]),_R=max(R,rs.pre[i]); if(digit[i]){ if(!ls.suf[i])R=_R; else if(!rs.pre[i])L=_L; else{ if(st.query(_L,ls.r)<st.query(rs.l,_R))L=_L; else R=_R; } }else{ if(!ls.suf[i])ret.v=min(ret.v,st.query(L,_R)); else if(!rs.pre[i])ret.v=min(ret.v,st.query(_L,R)); else ret.v=min({ret.v,st.query(L,_R),st.query(_L,R)}); } } return ret; } struct segT{ sgt tr[N<<2]; #define ls (node<<1) #define rs (node<<1|1) void push_up(int node){tr[node]=tr[ls]+tr[rs];} void cl(sgt &p,int x){ for(int i=30;i>=0;i--)p.suf[i]=p.pre[i]=(((b[x]>>i)&1)?x:0); p.v=(b[x]>v?a[x]:INF); p.l=p.r=x; } void build(int node,int l,int r){ if(l==r){ cl(tr[node],l); return; } int mid=(l+r)>>1; build(ls,l,mid);build(rs,mid+1,r); push_up(node); } void modify(int node,int l,int r,int x,int val){ if(l==r){ b[l]=val; cl(tr[node],l); return; } int mid=(l+r)>>1; if(mid>=x)modify(ls,l,mid,x,val); else modify(rs,mid+1,r,x,val); push_up(node); } sgt query(int node,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return tr[node]; int mid=(l+r)>>1; if(mid<ql)return query(rs,mid+1,r,ql,qr); if(mid+1>qr)return query(ls,l,mid,ql,qr); return query(ls,l,mid,ql,qr)+query(rs,mid+1,r,ql,qr); } }seg; int main(){ fastio; int tc;cin>>tc; while(tc--){ cin>>n>>v; v--; for(int i=30;i>=0;i--)digit[i]=((v>>i)&1); rep(i,1,n)cin>>a[i]; rep(i,1,n)cin>>b[i]; st.init(a,n); seg.build(1,1,n); int q;cin>>q; while(q--){ int op,i,x,l,r; cin>>op; if(op==1){ cin>>i>>x; seg.modify(1,1,n,i,x); }else{ cin>>l>>r; int ans=seg.query(1,1,n,l,r).v; if(ans==INF)cout<<-1<<' '; else cout<<ans<<' '; } } cout<<endl; } return 0;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具