• [P1020]导弹拦截 (贪心/DP/二分/单调队列)


    一道很经典的题

    这道题就是要求一个最长单调不升子序列和一个最长单调上升子序列。

    先打了一个n2复杂度的

    用DP

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10005
    int f[N],a[N];
    int n;
    int cnt1,cnt2,tot;
    int main()
    {
        while(scanf("%d",&a[++n])!=EOF);
        n--;
    //    cout<<n<<endl;
    //    for(int i=1;i<=n;++i)cout<<a[i]<<' ';cout<<endl;
        for(int i=1;i<=n;i++)
        {
            f[i]=1;
            for(int j=1;j<i;j++)
                if(a[i]<=a[j]&&f[i]<f[j]+1) f[i]=f[j]+1;
            if(f[i]>cnt1) cnt1=f[i];
        }
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        {
            f[i]=1;
            for(int j=1;j<=i;j++)
                if(a[i]>a[j]&&f[i]<f[j]+1) f[i]=f[j]+1;
            if(cnt2<f[i]) cnt2=f[i];
        }
        printf("%d
    %d
    ",cnt1,cnt2);
        return 0;
    }

    然后可以根据单调性进行优化

    但是思想就不一样了

    用二分简化成nlogn的

    #include<bits/stdc++.h>
    using namespace std;
    int a[100005],f[100005],l[100005];
    struct cmp{bool operator()(int a,int b){return a>b;}};
    int main()
    {
        int n=1;
        while(cin>>a[n])n++;
        n--;
        int con=1,cont=1;
        l[1]=f[1]=a[1];
        for(int i=2;i<=n;i++)
        {
            if(l[cont]>=a[i])l[++cont]=a[i];
            else l[upper_bound(l+1,l+cont+1,a[i],cmp())-l]=a[i];
            if(f[con]<a[i])f[++con]=a[i];
            else f[lower_bound(f+1,f+con+1,a[i])-f]=a[i];
        }
        cout<<cont<<" "<<con;
        return 0;
    }

    还有一个大佬的树状数组的

    我放在下面

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int f[1000000];
    int z[1000000];
    int lowbit(int x)
    {
        return x&-x;
    }
    int big;
    inline int ask(int x)//这是用来求单调上升子序列的
    {
        int r=0;
        for(int i=x;i>0;i-=lowbit(i))
            r=max(r,f[i]);
        return r;
    }
    inline void add(int x,int v)//这也是用来求单调上升子序列的
    {
        for(int i=x;i<=big;i+=lowbit(i))
            f[i]=max(f[i],v);
    }
    inline int que(int x)//这是用来求最长单调不升子序列的
    {
        int r=0;
        for(int i=x;i<=big;i+=lowbit(i))
            r=max(r,f[i]);
        return r;
    }
    inline void psh(int x,int v)//这也是用来求最长单调不升子序列的
    {
        for(int i=x;i>0;i-=lowbit(i))
            f[i]=max(f[i],v);
    }
    int tot;
    int a[1000000];
    int ans;
    int main()
    {
        tot=1;
        while(scanf("%d",&a[tot])!=EOF)
        {
            big=max(big,a[tot]);
            z[tot]=a[tot];
            tot++;
        }
        tot--;//读入并统计个数
        for(int i=1;i<=tot;i++)//求最长单升子序列,树状数组中保存的是0~a[i]的最大值
        {
            int x=ask(a[i])+1;
            ans=max(ans,x);
            add(a[i]+1,x);//因为是严格单升所以这里要+1
        }
        memset(f,0,sizeof(f));//清空树状数组,用来求下面的不降子序列
        int num=0;
        for(int i=1;i<=tot;i++)//求最长不降子序列,树状数组里存的是a[i]~inf的最大值
        {
            int x=que(a[i])+1;
            num=max(num,x);
            psh(a[i],x);//因为是不升而不是严格单降所以不用-1或+1
        }
        printf("%d
    %d",num,ans);
        return 0;
    }
    树状数组
  • 相关阅读:
    URL域名获取
    SQL Server 索引结构及其使用(二)
    SQL Server 索引结构及其使用(一)[转]
    查询数据库中所有表的数据量、有效数据量以及其它定制数据量
    转:Servlet的url匹配以及url-pattern详解
    转:在MyEclipse下创建Java Web项目 入门(图文并茂)经典教程
    MyEclipse +Servlet 乱码
    MyEclipse +Tomcat 异常操作
    Android Include标签
    转ATL对象类型
  • 原文地址:https://www.cnblogs.com/lincold/p/9933042.html
Copyright © 2020-2023  润新知