题解:P12555 [UOI 2024] AND Array
一个简单又好写的做法。
先不考虑所有的
发现一个重要性质:我们如果在
考虑定期重构,我们每隔
时间复杂度为
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int x=0;bool f=0;char ch=getchar();
while(ch<'0'||ch>'9')f^=(ch=='-'),ch=getchar();
while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int Maxn=1e5+5,B=1000;
int n,b;
int a[Maxn];
ll sum,ans[Maxn];
int last[1<<20],f[1<<20];
int main(){
n=read();b=read();
for(int i=1;i<=n;i++)a[i]=read();
memset(last,0x7f,sizeof last);
memset(f,0x7f,sizeof f);
int id=n+1;
for(int i=n;i;i--){
if(!a[i])sum+=i,a[i]=(1<<b)-1;
else{
last[a[i]]=i;
}ans[i]=sum*b;
if(i%B==0){
for(int i=0;i<(1<<b);i++)f[i]=last[i];
for(int i=0;i<b;i++)
for(int s=0;s<(1<<b);s++)if((s>>i)&1)f[s]=min(f[s],f[s^(1<<i)]);
id=i;
}
for(int j=0;j<b;j++){
int p=(1<<j);
for(int k=i;k<id;k++){
if(!(p&a[k]))p+=a[k],ans[i]+=k;
}while(f[(1<<b)-1-p]<=n)ans[i]+=f[(1<<b)-1-p],p+=a[f[(1<<b)-1-p]];
}
}
for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
return 0;
}