CF2147E
xujindong_ · · 题解
对于
现在直接模拟,复杂度
#include<bits/stdc++.h>
using namespace std;
int t,n,m,a[100005],temp[100005];
long long ans[32];
int main(){
ios::sync_with_stdio(0),cin.tie(0),cin>>t;
while(t--){
cin>>n>>m;
int s=0;
for(int i=1;i<=n;i++)cin>>a[i],s|=a[i];
memset(ans,0x3f,sizeof(ans)),ans[__builtin_popcount(s)]=0;
for(int i=0;i<=30;i++){
if(s>>i&1)continue;
long long num=0;
for(int j=1;j<=n;j++)temp[j]=a[j];
for(int j=i;j>=0;j--){
int now=0,pos=1,maxn=0;
for(int k=1;k<=n;k++)now|=temp[k];
if(now>>j&1)continue;
for(int k=1;k<=n;k++)if((temp[k]&((1<<j)-1))>=maxn)pos=k,maxn=temp[k]&((1<<j)-1);
num+=(1<<j)-maxn,temp[pos]+=(1<<j)-maxn;
}
s|=1<<i,ans[__builtin_popcount(s)]=num;
}
for(int i=30;i>=0;i--)ans[i]=min(ans[i],ans[i+1]);
for(int i=1,b;i<=m;i++)cin>>b,cout<<upper_bound(ans,ans+32,b)-ans-1<<'\n';
}
return 0;
}
还可以更快。先预处理,对每个位
#include<bits/stdc++.h>
using namespace std;
int t,n,m,a[100005],b[32][100005],mask;
long long ans[32];
bool vis[100005];
bool cmp(int x,int y){
return (a[x]&mask)>(a[y]&mask);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cin>>t;
while(t--){
int s=0;
memset(ans,0x3f,sizeof(ans)),cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i],s|=a[i];
ans[__builtin_popcount(s)]=0;
for(int i=0;i<=31;i++)for(int j=1;j<=n;j++)b[i][j]=j;
mask=(1ll<<31)-1,sort(b[31]+1,b[31]+n+1,cmp);
for(int i=30;i>=0;i--){
for(int j=1;j<=n;j++)b[i][j]=b[i+1][j];
int mid=1;
while(mid<=n&&a[b[i][mid]]>>(i+1)&1)mid++;
mask=(2ll<<i)-1,inplace_merge(b[i]+1,b[i]+mid,b[i]+n+1,cmp);
}
int p[32];
for(int i=0;i<=31;i++)p[i]=1;
for(int i=0;i<=30;i++){
if(s>>i&1)continue;
for(int j=1;j<=n;j++)vis[j]=0;
long long num=0;
for(int j=i;j>=0;j--){
while(p[j]<=n&&vis[b[j][p[j]]])p[j]++;
if(p[j]<=n&&~a[b[j][p[j]]]>>j&1)vis[b[j][p[j]]]=1,num+=(1<<j)-(a[b[j][p[j]]]&((1<<j)-1));
if(p[j]>n)num+=1<<j;
}
s|=1<<i,ans[__builtin_popcount(s)]=num;
}
for(int i=30;i>=0;i--)ans[i]=min(ans[i],ans[i+1]);
for(int i=1,b;i<=m;i++)cin>>b,cout<<upper_bound(ans,ans+32,b)-ans-1<<'\n';
}
return 0;
}