首页 > 代码库 > hust 1463 - 第二届“华为杯”初赛题目H

hust 1463 - 第二届“华为杯”初赛题目H

题目描述

m个盒子,第i个盒子的长尾hi,宽为wi。如果两个盒子i,j满足hi<hjwi<wj,则盒子i能够放入盒子j。按照上述要求堆放盒子,则最少能剩下多少堆?

输入

第一行有一个正整数 t ,表示数据组数(不多于20)。每组数据第一行为m,表示盒子个数,1 ≤ m ≤ 20000。接下来一样有2m个正整数w1h1,w2h2, ... ,wmhm,分别表示盒子尺寸。其中对于任何i,1 ≤ wihi ≤ 10000. 

输出

每一组测试数据输出一样,为最少的堆数。

样例输入

4
3
20 30 40 50 30 40
4
20 30 10 10 30 20 40 50
3
10 30 20 20 30 10
4
10 10 20 30 40 50 39 51

样例输出

1
2
3
2
看到题目大家都觉得很熟悉,不就是dp问题吗?可是n=20000;不能用n^2的dp,只能用nlgn的方法
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=20001;
struct node
{
    int x,y;
}box[maxn];
int a[maxn];
bool cmp(node xx,node yy)
{
    if (xx.x==yy.x) return xx.y<yy.y;
    else return xx.x>yy.x;
}
void find(int x,int y,int v)
{
    while (x<y)
    {
        int m=x+(y-x)/2;
        if (a[m]<=v) x=m+1;
        else y=m;
    }
    a[x]=v;
}
int main()
{
    int n,len,t;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        scanf("%d%d",&box[i].x,&box[i].y);
        sort(box+1,box+n+1,cmp);
        len=1;a[1]=box[1].y;
        for (int i=2;i<=n;i++)
        {
            if (box[i].y>=a[len]) a[++len]=box[i].y;
            else
            {
                find(1,len,box[i].y);
            }
        }
        printf("%d\n",len);
    }
    return 0;
}