在网上看了个思路,按x递增排序,x相同按y递减排序..然后求一个y的最长上升序列就行..这思路太神了,因为y在x相同的组内是递减的,所以找到一个更大的时,x一定更大..由于长度有10W,求上升序列的时候需要维护一个单调栈+二分,上升序列的长度就是栈的最大深度。路径没有特殊的要求,可行的都可以,每个点记录一下上一个的位置,最后递归或者循环一下输出就可以。

        

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=140000;
int n,p,q;
int stack[maxn];
int top;
int pre[maxn];
struct node
{
    int x,y,idx;
    bool operator<(const node& p)const
    {
       if (x!=p.x) return x<p.x;
       return y>p.y;
    }
    node(){}
    node(int a,int b,int c)
    {
        x=a;
        y=b;
        idx=c;
    }
}a[maxn];

void print(int k)
{
    if (k==-1) return;
    print(pre[k]);
    printf("%d ",a[k].idx);
}
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for (int i=0; i<n; i++)
    scanf("%d%d",&a[i].x,&a[i].y),a[i].idx=i+1;
    sort(a,a+n);
    memset(stack,0,sizeof stack);
    memset(pre,-1,sizeof pre);

    top=0;
    top++;
    stack[0]=-1;
    stack[top]=0;
    pre[0]=-1;
    int l,r,m;
    for (int i=1; i<n; i++)
    {
        if (a[i].y>a[stack[top]].y)
        {

            top++;
            stack[top]=i;
            pre[i]=stack[top-1];

        }
        else
        {
            l=1; r=top;
            while (l<r)
            {
                m=(l+r)>>1;
                if (a[stack[m]].y<a[i].y) l=m+1;
                else r=m;
            }
            stack[l]=i;
            pre[i]=stack[l-1];
        }
    }
    printf("%d\n",top);
    print(stack[top]);
    puts("");
    return 0;
}