在网上看了个思路,按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;
}