zoukankan      html  css  js  c++  java

  • 【问题背景】
      zhx 给他的妹子们排序。
    【问题描述】
      zhx 有 N 个妹子,他对第 i 个妹子的好感度为a[i], 且所有a[i],两两不相等。现在 N 个妹子随意站成一排,他要将她们根据好感度从小到大排序。他使用的是冒泡排序算法(详见下)。

      如果排序过程中好感度为a[i]的妹子和好感度为a[j]的妹子发生了交换,那么她们之间会发生一场口角。 现在 zhx 想知道,给定妹子的初始排列,在排序完成后,最多存在多少个妹子,她们任意两人之间没发生过口角。
      正式地,考虑对数组a[i]进行冒泡排序,如果a[i]和a[j]在排序过程中发生交换,那么在两个元素之间连一条边。你需要求出,排序结束后,最多存在多少个元素,其中任意两个元素之间不存在连边。冒牌排序算法如下:



    【输入格式】
      第一行两个整数 N,表示妹子数量。
      接下来一行 N 个整数a[i],表示初始第 i 个妹子的好感度。
    【输出格式】
      一行一个整数,表示最多满足要求的妹子的个数。 
    【样例输入】
      3
      3 1 2
    【样例输出】
      2
    【样例解释】
      {1, 2}。
    【数据规模与约定】
    对于30%的数据,1 ≤ N ≤ 16。
    对于70%的数据,1 ≤N ≤ 5000。
    对于100%的数据,1 ≤ N ≤ 100000, 0 ≤ a[i] < N。

    【题目分析】

        最长上升子序列,因为我们要找的是一个最大的集合,在这个集合中所有的妹子都没有发生口角,那让这些妹子不发生口角的办法就是不交换,怎样做到不交换,如果初始状态已经是a[i]<a[j],就不需要交换,那就要找最长上升子序列。

    //dp做法超时继续,
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=100010;
    int a[maxn],bh[maxn];
    bool isno[maxn]={0};
    int n,ans=0;
    int dp[maxn];
    int LIS(int n)
    {  
        int sum=1;  
        for (int i=2;i<=n;i++)  
        {  
            int tmp=i;  
            int maxx=0;  
            for (int j=1;j<i;j++)  
            {
                if (a[i]>a[j])  
                    maxx=max(maxx,dp[j]);  
            }
            dp[i]=maxx+1;
            if (dp[i]>sum)  
                sum=dp[i];  
        }
        return sum;  
    }  
    int main()  
    {
        freopen("sort.in","r",stdin);
        freopen("sort.ans","w",stdout);
        dp[1]=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int ans=LIS(n);
        if(ans==1)
            printf("0");
        else
            printf("%d
    ",ans);
        return 0;  
    }  
    //用二分nlogn
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int n,ans=1;
    int Stack[100010],a[100010];
    //Stack单调递增 
    int find(int x)
    {
        int l=1,r=ans;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(x>Stack[mid]&&x<=Stack[mid+1])
                return mid;
            else if(x>Stack[mid])
                l=mid+1;
            else r=mid-1; 
        }
        return 0;
    }
    int main()
    {
        freopen("sort.in","r",stdin);
        freopen("sort.ans","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        Stack[1]=a[1];
        int t;
        for(int i=2;i<=n;i++)
        {
            if(a[i]>Stack[ans])
                t=++ans;
            else
                t=find(a[i])+1;//因为search找到的是当前点的坐标,要想使T发挥它的最大价值,应该把他放在当前点的上一个点
            Stack[t]=a[i];
        }
        printf("%d",ans);//单调栈的长度即为LIS长度
        fclose(stdin);fclose(stdout);
        return 0;
    }
  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/xiaoningmeng/p/6000512.html
Copyright © 2011-2022 走看看