• 牛客网 牛客练习赛16 E.求值


    链接:https://www.nowcoder.com/acm/contest/84/E
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld
    题目描述
    给定n个数字a1, a2, ..., an。
    定义f(l, r) = al | al+1| ... | ar。
    现在枚举(1 <= l <= r <= n),问不同的f值一共有多少个。
    输入描述:

    第一行一个整数n表示数组大小 (1 <= n <= 100,000);
    第二行n个整数满足0 <= ai <= 1000,000。

    输出描述:

    输出一个整数表示不同的f值一共有多少个。

    示例1
    输入

    3
    1 2 0

    输出

    4

    示例2
    输入

    10
    1 2 3 4 5 6 1 2 9 10

    输出

    11

    分析:可以发现,根据题目的范围,每个数最多有20个二进制位,所以我们可以先枚举每个区间开头的数,比如现在枚举到了i,那么它产生新值的下一个位置的数,应在i为0的二进制位上,新数的该位为1,且为了不遗漏,新数必须最近。。而为了找到这个最近的位置,可以进行预处理,Next[i][j]用来表示从第i个数开始,第j个二进制位为1的最近的位置,这样的话时间复杂度就是O(20*20*n),能够满足。

    代码如下:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int MAXN=1e5+100;
    int vis[1000010*2];
    int Next[MAXN][22];
    int a[MAXN];
    int tmp;
    int main()
    {
        int n;
        int ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
        scanf("%d",&a[i]);
         if(a[i]==0&&!vis[0])
         {
         vis[0]=1;
         ans++;
         }
        }
    
        for(int i=0;i<=19;i++)
        {
          if(a[n]&(1<<i))
          Next[n][i]=n;
          else
          Next[n][i]=n+1;
        }
        for(int i=n-1;i>=1;i--)
        {
            for(int j=0;j<=19;j++)
            {
               if(a[i]&(1<<j))
               Next[i][j]=i;
               else
               Next[i][j]=Next[i+1][j];
            }
        }
        for(int i=1;i<=n;i++)
        {
           int p=i;
           int now=0;
           while(1)
           {
    
              int minpos=MAXN;
    
              for(int j=0;j<=19;j++)
              {
                  if(!(now&(1<<j)))
                  minpos=min(minpos,Next[p][j]);
              }
              if(minpos>n)break;
              now|=a[minpos];
              if(!vis[now])
              {
                  vis[now]=1;
                  ans++;
              }
              p=minpos;
           }
        }
        printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    继承映射
    一对多,多对一,自关联的配置
    Spring 配置自动扫描spring bean配置
    Dao 处理
    2019暑假集训 括号匹配
    2019暑假集训 BLO
    2019暑假集训 Intervals
    2019暑假集训 平板涂色
    2019暑假集训 走廊泼水节
    0002-五层小山
  • 原文地址:https://www.cnblogs.com/a249189046/p/8974817.html
Copyright © 2020-2023  润新知