CF243A The Brand New Function
题面传送门
题解里居然没有对这个东西复杂度严格证明的,我来补一发。
首先暴力\(O(n^2)\)不再赘述。
可以加上一些剪枝,如果我们对于每个\(i\)倒序枚举每个\(j\),那么如果\(a_j|a_{j+1}|⋯|a_i=a_j|a_{j+1}|⋯|a_{i-1}\),那么就不用往下枚举,因为接下来的一定与前一个所枚举的相同。
然后,就过了。
代码实现:
#include<cstdio>
using namespace std;
int n,m,k,x,y,z,a[100039],f[2000039],ans;
int main(){
//freopen("1.in","r",stdin);
register int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=n;i++){
if(!f[a[i]]) ans++,f[a[i]]=1;
for(j=i-1;j;j--){
if(a[j]==(a[i]|a[j])) break;
a[j]|=a[i];
if(!f[a[j]]) ans++,f[a[j]]=1;
}
}
printf("%d\n",ans);
}
那么为什么这样子复杂度是对的呢?这样子看上去就是\(O(n^2)\)的。
观察a[j]|=a[i];
这条语句,即如果进入这条语句,\(a_j\)至少有一个二进制位由\(0\)变成\(1\),则对于每个\(a_j\),最多只会被操作\(loga_j\)次,则总复杂度为\(O(nloga_i)\),可以通过本题。