【?? 记录】P9696 [GDCPC2023] Swapping Operation
首先,如果 swap,那么
不妨提取出改变前缀
如果交换非两个关键点,对应的前缀/后缀权值不会变大,因此不优。
如果交换一个关键点,一个非关键点。不妨假设是枚举的前缀关键点
枚举
如果交换两个关键点,暴力枚举后计算。
复杂度
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005,maxk=19,S=(1<<30)-1;
int n,m,T,ans;
int a[maxn],lg[maxn],st[maxk][maxn],pv[maxn],ispre[maxn],issuf[maxn],mx[maxn];
vector<int>pre,suf;
map<int,vector< pair<int,int> >>mp;
int query(int l,int r){
if(l>r)
return S;
int k=lg[r-l+1];
return st[k][l]&st[k][r-(1<<k)+1];
}
void calc(){
pv[0]=S;
for(int i=1;i<=n;i++)
pv[i]=pv[i-1]&a[i];
for(int i=n,v=S;i>1;i--){
v&=a[i],ans=max(ans,pv[i-1]+v);
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n),ans=0,lg[0]=-1;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),st[0][i]=a[i],lg[i]=lg[i>>1]+1,ispre[i]=issuf[i]=0;
for(int i=1;i<=18;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
st[i][j]=st[i-1][j]&st[i-1][j+(1<<(i-1))];
pre.clear(),suf.clear();
for(int i=1,now=S;i<=n;now&=a[i],i++)
if((now&a[i])<now)
pre.emplace_back(i),ispre[i]=1;
for(int i=n,now=S;i>=1;now&=a[i],i--)
if((now&a[i])<now)
suf.emplace_back(i),issuf[i]=1;
calc();
for(int i=0;i<pre.size();i++)
for(int j=0;j<suf.size();j++)
swap(a[pre[i]],a[suf[j]]),calc(),swap(a[pre[i]],a[suf[j]]);
mp.clear();
for(int i=0;i<pre.size();i++)
for(int j=pre[i];j<n;j++){
int v=query(1,pre[i]-1)&query(pre[i]+1,j);
mp[v].emplace_back(make_pair(j+1,query(j+1,n)&a[pre[i]]));
}
for(map<int,vector<pair<int,int>>>::iterator it=mp.begin();it!=mp.end();it++){
int v=it->first;
mx[n+1]=-2e9;
for(int i=n;i>=1;i--){
mx[i]=mx[i+1];
if(issuf[i]==0)
mx[i]=max(mx[i],v&a[i]);
}
vector<pair<int,int>>V=it->second;
for(int i=0;i<V.size();i++)
ans=max(ans,mx[V[i].first]+V[i].second);
}
mp.clear();
for(int i=0;i<suf.size();i++)
for(int j=1;j<suf[i];j++){
int v=query(j+1,suf[i]-1)&query(suf[i]+1,n);
mp[v].emplace_back(make_pair(j,query(1,j)&a[suf[i]]));
}
for(map<int,vector<pair<int,int>>>::iterator it=mp.begin();it!=mp.end();it++){
int v=it->first;
mx[0]=-2e9;
for(int i=1;i<=n;i++){
mx[i]=mx[i-1];
if(ispre[i]==0)
mx[i]=max(mx[i],v&a[i]);
}
vector<pair<int,int>>V=it->second;
for(int i=0;i<V.size();i++)
ans=max(ans,mx[V[i].first]+V[i].second);
}
printf("%d\n",ans);
}
return 0;
}