SPOJ 3937 - Wooden Sticks 最长上升子序列LIS

给了n个(n<=5000)木棍的长度hi与宽度wi(均小于10000),现在机器要打磨这些木棍,如果相邻连个木棍hi<=hj并且wi<=wj就不需要调整机器,问如何排序使得机器调整的次数最少。

【LIS】基本上和【这题】相同,但是那题中,如果hi=hj并且wi=wj长度会增加,而这道题则相反。

还是类似于那一题的思路:

假设wi>wj,如果hi>=hj,显然符合条件,答案不需要增加。

还是wi>wj,如果hi<hj,那么答案+1

假设wi=wj,如果hi>=hj,那么答案也是不需要增加。

由于要使机器调整次数尽量小,因此把w降序排列,当wi=wj时,让hi>=hj(h降序排列),然后对h求最长严格上升子序列即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 5005
#define MAXM 40005
#define INF 0x3fffffff
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
bool flag;

struct node
{
    int s,b,i;
}p[MAXN];

int dp[MAXN];

bool cmp(node x,node y)
{
    if (x.s==y.s) return x.b>y.b;
    return x.s>y.s;
}

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);

        for (i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].s,&p[i].b);
            p[i].i=i;
        }
        sort(p+1,p+1+n,cmp);

        num=0;
        for (i=1;i<=n;i++)//求最长上升子序列
        {
            if (p[i].b>dp[num])
            {
                dp[++num]=p[i].b;
            }else
            {
                k=lower_bound(dp+1,dp+1+num,p[i].b)-dp; 

                dp[k]=p[i].b;
            }
        }

        printf("%d\n",num);
    }
    return 0;
}
时间: 2024-10-11 04:10:23

SPOJ 3937 - Wooden Sticks 最长上升子序列LIS的相关文章

poj1836——dp,最长上升子序列(lis)

poj1836——dp,最长上升子序列(lis) Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13767   Accepted: 4450 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight

最长上升子序列LIS模板

1 ///最长上升子序列LIS模板 2 int BinSerch(int l,int r,int cut) 3 { 4 while (l<=r) 5 { 6 int m=(l+r)>>1; 7 if (cut>d[m]&&cut<=d[m+1]) return m; 8 if (cut>d[m]) l=m+1; 9 else r=m-1; 10 } 11 return 0; 12 } 13 14 int LIS(int n) 15 { 16 int le

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

最长上升子序列LIS解法(n^n &amp;&amp; nlogn)

最长递增子序列问题 在一列数中寻找一些数满足 任意两个数a[i]和a[j] 若i<j 必有a[i]<a[j] 这样最长的子序列称为最长递增子序列LIS LIS问题有两种常见的解法 一种时间复杂度n^n 一种时间复杂度nlogn 下面我们先来说一下n^n的算法 设dp[i]表示以i结尾的最长上升子序列的长度 把问题分解 分解成序列中每一项最为终点的最大上升子序列 从第二项开始依次判断 最后找出最大的一项就是答案 则状态转移方程为 dp[i] = max{dp[j]+1}, 1<=j<

SPOJ MSTICK. Wooden Sticks 贪心 结构体排序

MSTICK - Wooden Sticks There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine

算法面试题 之 最长递增子序列 LIS

找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E6%95%B0%E7%BB%84%E9%83%BD%E6%B2%A1%E7%BB%99%E5%87%BA%E6%9D%A5 我就是理解了一下他的分析 用更通俗易懂的话来说说题目是这样 d[1..9] = 2 1 5 3 6 4 8 9 7 要求找到最长的递增子序列首先用一个数组b[] 依次的将d里面

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已经做了实现,但是这种方法时间复杂度太高,查阅相关资料后我发现有人提出的算法可以将时间复杂度降低为O(nlogn),这种算法的核心思想就是替换(二分法替换),以下为我对这中算法的理解: 假设随机生成的一个具有10个元素的数组arrayIn[1-10]如[2, 3, 3, 4, 7, 3, 1, 6,

最长上升子序列 LIS nlogn

给出一个 1 - n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的n个整数组成的序列. Output 最长上升子序列的长度 题解 这里给出两种方法,先说经典版本的,设dp[i]表示以以 a[i]为结尾的LST的长度,n方的暴力很好想,显然我们在i之间找到一个最大的LST,且要保证a[j]<a[i],那么显然dp[i]=max(dp[i],dp[j]+1),那么这个dp显然就是在i之前找到一个以小于a[i]结尾元

最长上升子序列 (LIS算法(nlong(n)))

设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F [t] = 0(t = 1, 2, ..., len(A)).则有动态规划方程:F[t] = max{1, F[j] + 1} (j = 1, 2, ..., t - 1, 且A[j] < A[t]). 现在,我们仔细考虑计算F[t]时的情况.假设有两个元素A[x]和A[y],满足 (1)x < y < t (2)A[x] < A[y] < A[t] (3)F[x] =