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

来源:互联网 发布:网络销售聊天技巧话术 编辑:程序博客网 时间:2024/05/29 15:14

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 SiSj and BiBj or if SiSj and BiBj (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, Bi109 ).

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<=nSi>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
原创粉丝点击