P9747
i_am_not_feyn · · 题解
个人认为 CSP 应该并不会考什么复杂的 DS,这道题的难度基本上都在实现上了。
首先观察一个序列合法的条件。
注意到操作并不会使得某一个一开始存在的二进制位消失,并且要求最后的序列全为一个数,那么显然这个数就是整个序列的或。
下文中令四元组
令这个数为
若有一个
故而一个序列是合法的当且仅当可以找到一个
对于原序列的每个位置
-
l_i\ge L_i,l_i\ge l' -
r_i\le R_i,r_i\le r'
只考虑 1 的情况,2 的话倒着再做一遍就是。接下来就是没有脑子的套路了。
显而易见的,将
由于不好处理
A 中元素的贡献是
B 中元素的贡献是
时间是
code
#include<bits/stdc++.h>
using namespace std;
const int N=4e6+50,M=8e6+50,inf=1e9+7;
namespace IO {
//IO 由于是贺别人的所以不是很能放出来
} // IO
using namespace IO;
int T,Tid,n,q,a[N],m=30,Ans[N];
struct ask
{
int l,r,id;
friend bool operator<(ask a,ask b)
{
return a.l<b.l;
}
}Q[N];
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
class sukwants
{
public:
int mx[M],d,val,L,R,ans;
void add(int x,int l,int r)
{
if(l==r)return void(mx[x]=val);
if(d<=mid)add(ls,l,mid);
else add(rs,mid+1,r);
mx[x]=max(mx[ls],mx[rs]);
}
void find(int x,int l,int r)
{
if(L<=l&&R>=r)return void(ans=max(ans,mx[x]));
if(L<=mid)find(ls,l,mid);
if(R>mid)find(rs,mid+1,r);
}
void add(int a,int b){d=a,val=b;add(1,1,n);}
int find(int l,int r){L=l,R=r;ans=0;find(1,1,n);return ans;}
}sgt;
class sukwats
{
public:
int val[M],w[M],L,R,d,ans;
void Insert(int x,int l,int r)
{
if(L<=l&&R>=r)return void(val[x]=max(val[x],d));
if(L<=mid)Insert(ls,l,mid);
if(R>mid)Insert(rs,mid+1,r);
}
void Add(int x,int l,int r)
{
if(L<=l&&R>=r)return void(w[x]=max(w[x],d));
if(L<=mid)Add(ls,l,mid);
if(R>mid)Add(rs,mid+1,r);
}
void find(int x,int l,int r)
{
ans=max(ans,max(val[x],w[x]+d));
if(l==r)return;
return (d<=mid)?find(ls,l,mid):find(rs,mid+1,r);
}
void insert(int l,int r,int v){L=l,R=r,d=v;Insert(1,1,n);}
void add(int l,int r,int v){L=l,R=r,d=v;Add(1,1,n);}
int find(int x){d=x;ans=0;find(1,1,n);return ans;}
}sgc;
void dfs(int x,int l,int r)
{
sgt.mx[x]=0;sgc.val[x]=sgc.w[x]=-inf;
if(l!=r)dfs(ls,l,mid),dfs(rs,mid+1,r);
}
int L[N],R[N],rel[N],rer[N],fir[2][32],las[2][32];
class shabi_ds
{
public:
int a[N],L[N],R[N],re[N];
vector<int>in[N],out[N];
void clear()
{
for(int i=1;i<=n;i++)vector<int>().swap(in[i]),vector<int>().swap(out[i]);
}
void pre()
{
sort(Q+1,Q+1+q);dfs(1,1,n);clear();
for(int i=1;i<=n;i++)if(re[i]>=L[i])in[re[i]].push_back(i),out[L[i]].push_back(i);
}
void solve()
{
pre();int pos=q;
for(int i=n;i>=1;i--)
{
for(auto x:in[i])sgt.add(x,R[x]);
for(auto x:out[i])
{
sgt.add(x,0),sgc.add(x,R[x],-L[x]+1),sgc.insert(R[x],n,R[x]-L[x]+1);
}
while(pos&&Q[pos].l==i)
{
int x=min(Q[pos].r,sgt.find(Q[pos].l,Q[pos].r)),y=sgc.find(Q[pos].r);
Ans[Q[pos].id]=max(Ans[Q[pos].id],max(x-i+1,y)),pos--;
}
}
}
}A,B;
void init()
{
for(int i=1;i<=n;i++)L[i]=1,R[i]=n,rel[i]=rer[i]=i;
for(int i=0;i<=m;i++)fir[1][i]=0,las[1][i]=n+1;
for(int ty=0,i=1;i<=n;i++,ty^=1)for(int j=0;j<=m;j++)
if((a[i]>>j)&1)rel[i]=min(rel[i],fir[ty^1][j]),fir[ty][j]=i;
else fir[ty][j]=fir[ty^1][j],L[i]=max(L[i],fir[ty][j]+1);
for(int ty=0,i=n;i>=1;i--,ty^=1)for(int j=0;j<=m;j++)
if((a[i]>>j)&1)rer[i]=max(rer[i],las[ty^1][j]),las[ty][j]=i;
else las[ty][j]=las[ty^1][j],R[i]=min(R[i],las[ty][j]-1);
for(int i=1;i<=n;i++)
{
A.L[i]=L[i],A.R[i]=R[i],A.re[i]=rel[i];
B.R[n-i+1]=n-L[i]+1,B.L[n-i+1]=n-R[i]+1,B.re[n-i+1]=n-rer[i]+1;
}
}
void sol()
{
read(n);read(q);
for(int i=1;i<=n;i++)read(a[i]),A.a[i]=B.a[n-i+1]=a[i];
for(int i=1;i<=q;i++)read(Q[i].l),read(Q[i].r),Q[i].id=i,Ans[i]=1;
init();A.solve();
for(int i=1;i<=q;i++)Q[i].l=n-Q[i].l+1,Q[i].r=n-Q[i].r+1,swap(Q[i].l,Q[i].r);
B.solve();
for(int i=1;i<=q;i++)write(Ans[i]);
}
main()
{
read(T),read(Tid);
while(T--)sol();
}