zoj1283(LIS)

题意:宝藏在一些点中,只能从(0,0)出发,每次只能向右(x+1,y)或是向上走(x,y+1)。问要走几趟才能取完宝藏。


解法:按x,y分别为第一二关键字排序,那么一趟下来,y坐标是个非递减序列。然后转化成问y方向能由最少为多少的非递减序列个数组成。这个等效于求严格递减序列的长度。即nlogn求最长严格递减序列长度即可。


代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;


#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=100010;
const LL INF=0x3FFFFFFF;
int  N, M ,P;


struct point
{
    int x,y;
} points[Max];
int num[Max];
bool operator<(const point& a,const point& b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
struct cmp
{
    int operator()(const int& a,const int& b)
    {
        return a>b;
    }
};
int up[Max];//up[j]表示从num[0]到num[j],以num[j]结尾的最长升序长度


int D[Max];//辅助数组
int getLIS(int num[],int n)//up[j]表示从num[0]到num[j],以num[j]结尾的最长升序长度
{
    int last=0;
    int ans=0;
    for(int i=0; i<n; i++)
    {
        up[i]=lower_bound(D,D+last,num[i],cmp())-D+1;//lower_bound计算的是严格升序 upper_bound计算的是非严格升序(可以相等)
        if(up[i]>last) D[last = up[i]]=num[i];
        D[up[i]-1]=num[i];//更新D[k]为最小的
        ans=max(ans,up[i]);
    }
    return ans;
}
bool operator==(const point& a,const point& b)
{
    if(!(a<b)&&!(b<a))
        return true;
    return false;
}
int main()
{
    while(scanf("%d%d%d",&N,&M,&P)==3)
    {
        for(int i=0; i<P; i++)
        {
            scanf("%d%d",&points[i].x,&points[i].y);
        }
        //cout<<P<<endl;
        sort(points,points+P);
        for(int i=0; i<P; i++)
            num[i]=points[i].y;
        cout<<getLIS(num,P)<<endl;
    }
    return 0;
}
/*
100 100 8
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2


2 5 8
1 4 7
0 3 6
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值