zoukankan      html  css  js  c++  java
  • 绝世好题(DP)

    题目链接:绝世好题

    暴力就不用说了,和lis神似,O(n2)妥妥的挂掉,但可以得大部分分(好像是90,80)...

    考虑优化,来一发非正解的优化:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=101000;
    int n,a[N],f[N],ans,tot;
    priority_queue<pair<int,int> >q;
    struct gg
    {
        int x,y;
    }b[N];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff; 
    }
    inline int dfs(int x)
    {
        if(q.empty()) return 0;
        int x1=q.top().first;
        int x2=q.top().second;
        if((x&x2)==0){b[++tot].x=x1;b[tot].y=x2;q.pop();return (dfs(x));}
        else return x1; 
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        n=read();
        for(register int i=1;i<=n;++i) a[i]=read();
        for(register int i=1;i<=n;++i)
        {
            tot=0;
            f[i]=dfs(a[i])+1;q.push(make_pair(f[i],a[i]));
            ans=max(ans,f[i]);
            for(register int j=1;j<=tot;++j) q.push(make_pair(b[j].x,b[j].y));
        }
        printf("%d",ans);
        return 0;
    } 

    其实优化很显然,我们用大根堆维护一个最大的f[j](j<i)和他的权值,每次更新i时,从大跟堆中弹出来最大的,检验是否符合条件,不符合再弹,其实最坏的复杂度还是O(n2logn)但考虑到数据不会正好卡,且每次查询的第一个最大的,大概率会符合条件,所以...就过了;

    这里要说的不是暴力有多优秀,而是我们在优化某些算法时,考虑多枚举了那些无用的元素,想办法将他剪掉就可以了,尽量让电脑做有用功...

    之后考虑正解,是与二进制有关的,这也是我第一次有点认真的啃二进制的知识...

    我们思考一个数i,它的前继j和他&不为0,也就是说,i和j在二进制位上,至少有一个位上两个都是1,那我们就可以将信息放在这一位上,因为我们可以查询i的每一位,为1,就可以将上一个距离他最近的那一位也为1的j转移过来.可以用f[i]表示在当前状态下,第i个数为1的数的最长序列长度.

    考虑过转移,之后考虑怎么更新f数组。对于i我们在各个为1的位上去个max作为它的前继,那怎么将第i个数的长度最长为k记录下来呢?我们可以思考之后的数如果将i作为前继,那么必须和i有一个位上都为1,那这就好办了,我们在i为1的每一个位上都更新成刚才取得max,这样状态就记录下来...

    #include<bits/stdc++.h>
    using namespace std;
    int n,f[35],s1,s,ans;
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    } 
    int main()
    {
        freopen("1.in","r",stdin);
        n=read();
        for(register int i=1;i<=n;++i)
        {
            int x=read();s1=x;s=0;
            for(register int j=1;s1;++j)
            {
                if(s1&1) s=max(s,f[j]);
                s1>>=1;    //对所有为1的位取max作为前继 
            } 
            s1=x;
            for(register int j=1;s1;++j)
            {
                if(s1&1) f[j]=s+1;  //对所有为1的位更新成当前的最大值. 
                s1>>=1; 
            } 
        }
        for(register int i=1;i<=32;++i) ans=max(ans,f[i]);
        printf("%d",ans);
        return 0; 
    } 
  • 相关阅读:
    Nbear实体和接口 CodeSmith模版
    prototype1.4版中文参考手册(word,pdf,chm)
    SharePoint 2013 (SharePoint 15)的新特性
    没有域环境下安装SharePoint 2010
    产品经理(PM)常用原型图设计工具
    【转贴】mysql导入数据load data infile用法
    重新学javaweb!
    关于HIbernate中的lazy属性的一些解释
    JAVA程序员基本测试题目
    添加sql server约束
  • 原文地址:https://www.cnblogs.com/gcfer/p/11690803.html
Copyright © 2011-2022 走看看