SGU 199. Beautiful People(最长上升子序列nlogn LIS)

Problem Statement

    The most prestigious sports club in one city has exactly N members. Each of its members is strong and beautiful. More precisely, i-th member of this club (members being numbered by the time they entered the club) has strength Si and beauty Bi . Since this is a very prestigious club, its members are very rich and therefore extraordinary people, so they often extremely hate each other. Strictly speaking, i-th member of the club Mr X hates j-th member of the club Mr Y if Si Sj and Bi Bj or if Si Sj and Bi Bj (if both properties of Mr X are greater then corresponding properties of Mr Y, he doesn’t even notice him, on the other hand, if both of his properties are less, he respects Mr Y very much).
    To celebrate a new 2003 year, the administration of the club is planning to organize a party. However they are afraid that if two people who hate each other would simultaneouly attend the party, after a drink or two they would start a fight. So no two people who hate each other should be invited. On the other hand, to keep the club presti≥ at the apropriate level, administration wants to invite as many people as possible.
    Being the only one among administration who is not afraid of touching a computer, you are to write a program which would find out whom to invite to the party.

Input

    The first line of the input file contains integer N — the number of members of the club. ( 2 ≤ N ≤ 100,000 ). Next N lines contain two numbers each — Si and Bi respectively ( 1 ≤ Si , Bi 109 ).

Output

    On the first line of the output file print the maximum number of the people that can be invited to the party. On the second line output N integers — numbers of members to be invited in arbitrary order. If several solutions exist, output any one.

Example

Input
    4
    1 1
    1 2
    2 1
    2 2
Output
    2
    1 4

题意

    一个俱乐部里一共有n个人,每个人有两个值,力量S和美丽B,让你求出一组人,使得这一组人里面对于每个人i, 1<i<=n Si>Si1 and Bi>Bi1 ,并且人数要最多。简单说就是要求一个二维最长上升子序列。

思路

    首先由题意得,这题要求的是二维的最长上升子序列,而根据数据范围来看,还是要nlogn的,如果两维一起做的话大概是不可行的,而两维分开做,求出的最长上升子序列又有很大可能是不一样的。所以我们有这样一种想法,对于所有人我们先排序,将S从小到大排序并将S相等的人将B从大到小排序,这样我们就可以只用对B这一维进行最长上升子序列了。因为这样排序的话,S相等的,B最大的都在最前面,后面的不会影响。还有,这题需要打印一组可行的解,我们对于每一位,记录一个pre,表示这一位的前面符合的第一个是哪一位,最后只要递归打印就可以出解了。

Code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void readInt(int &x) {
    x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    x*=f;
}
inline void readLong(ll &x) {
    x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    x*=f;
}
/*================Header Template==============*/
const ll base=1e9;
ll x[100010],idx[100010];
int n,len,pre[100010];
struct peo{ll x,y;int id;}p[100010];
inline bool cmp(peo a,peo b){return a.x==b.x?a.y>b.y:a.x<b.x;}
inline void print(int ans) {
    if(ans==0)
        return;
    print(pre[ans]);
    printf("%d",p[ans].id);
    putchar(x[len]==ans?'\n':' ');
}
int main() {
    readInt(n);
    for(int i=1;i<=n;i++) {
        p[i].id=i;
        readLong(p[i].x);
        readLong(p[i].y);
    }
    sort(p+1,p+n+1,cmp);
    x[1]=1;
    int len=1;
    for(int i=2;i<=n;i++) {
        int l=1,r=len;
        while(l<=r) {
            int mid=(l+r)>>1;
            if(p[x[mid]].y<p[i].y)
                l=mid+1;
            else
                r=mid-1;
        }
        x[l]=i;
        pre[i]=x[l-1];
        len=max(len,l);
    }
    printf("%d\n",len);
    print(x[len]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值