zoukankan      html  css  js  c++  java
  • bzoj4300 绝世好题(位运算+DP)

    为什么要写这道题呢?因为它是“绝世好题”。

    题意:给定n个数,在其中找出一段子序列b,使得b[i]&b[i-1]!=0,求出满足条件的最长子序列长度。

    输入:第一行:一个整数n,表示数列的个数。

               第二行:n个整数,表示数列a。

    输出:一行,一个整数,表示最长的子序列长度。

    输入样例:

    3
    1 2 3

    输出样例:

    2

    解析:若b[i]&b[i-1]!=0,即b[i]与b[i-1]在二进制下有一位相同且都为1。那么设dp[i]表示前i个数所能达到的最长子序列长度,那么在转移时只需枚举是从二进制下的第几位转移过来的便好了。由于在转移时还要枚举是从哪个位置转移过来的,所以时间复杂度为o(n^2log(n)),但由于每次进行转移时是在前面的状态中找一个最大的,所以显然可以用堆进行优化,时间复杂度(o(nlog(n)^2))。(这题其实有o(nlog(n))的做法,而且大家好像都是这么写的,可我做的时候没想到(果然我还是菜!))。

    代码如下:

     1 #include<cstdio>
     2 #include<vector>
     3 #include<queue>
     4 using namespace std;
     5 
     6 const int MAXN=100010;
     7 int n,a[MAXN],dp[MAXN],ans;
     8 vector <int> ve[MAXN];
     9 priority_queue <int> heap[33];
    10 
    11 int read(void) {
    12     char c; while (c=getchar(),c<'0' || c>'9'); int x=c-'0';
    13     while (c=getchar(),c>='0' && c<='9') x=x*10+c-'0'; return x;
    14 }
    15 
    16 void solve(int x,int p) { //预处理出二进制下1的个数 
    17     int bit=0;
    18       while (x>0) {
    19           bit++;
    20           if (x&1) {
    21               ve[p].push_back(bit);
    22           }
    23           x>>=1;
    24       }
    25 }
    26 
    27 int main() {
    28     n=read();
    29       for (int i=1;i<=n;++i) a[i]=read();
    30       for (int i=1;i<=n;++i) solve(a[i],i);
    31       for (int i=1;i<33;++i) heap[i].push(0);
    32       for (int i=1;i<=n;++i) {
    33           for (int j=0;j<ve[i].size();++j) {
    34               int u=ve[i][j];
    35               dp[i]=max(dp[i],heap[u].top()+1); //从堆中取出一个最大的进行转移 
    36           }
    37         for (int j=0;j<ve[i].size();++j) //将这一个状态加入堆中 
    38           heap[ve[i][j]].push(dp[i]);
    39       }
    40       for (int i=1;i<=n;++i) //找出最长的子序列 
    41         for (int j=0;j<ve[i].size();++j) ans=max(ans,dp[i]);
    42     printf("%d",ans);
    43     return 0;
    44 }
  • 相关阅读:
    接口内容小结
    接口的静态方法与私有方法
    接口的默认方法
    发红包O
    抽象
    《大道至简》读后感
    重写
    继承中的二义性问题
    数学应用
    继承
  • 原文地址:https://www.cnblogs.com/Gaxc/p/9745620.html
Copyright © 2011-2022 走看看