题意是:有很多人,有智慧值和魅力值,必须每个人全都比别人高或者都比别人低才行,否则会打架,现在求出最多的不会打架的人数参加晚会
这道题目刚开始听比人说是第一重顺序排序,第二重逆序排序,然后求最长上升子序列,其实并没有想象中的那么简单,1 10,2 12,3 1这组数据如果按照上述说法的话排出来是错的,因为需要输出下标,很显然是错的,那么现在该怎么操作呢,需要一个path数组存放某些东西,刚开始的时候,我存放的是数据的下标,后来发现上述的情况考虑不到,那咋办呢,path可以用来存放该元素在“队列里”现在所处的位置是第几个位置,这里可以用二分去查找,这样的话,长度最起码是没变的,然后关键点来了,为什么我要第二重倒序呢,正序不可以吗,如果要是正序的话1 1,1 2,2 1,2 2,那么path数组的值分别为1,2,1,2,无论是从倒序还是正序找都不是正确答案,那么为什么要逆序排序,倒序去找呢,因为倒着的话下面的最大的会和上面最小的在一块,这样的话,就解决了一切问题
#include <iostream>
#define INF -9999999999
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=100005;
struct sa
{
int x,y;
int p;
};
int cmp2(const sa a,const sa b)
{
if(a.x==b.x)
return a.y>b.y;
else return a.x<b.x;
}
sa a[maxn];
int dp[maxn],path[maxn];
int main()
{
int n;
while(cin>>n)
{
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=1; i<=n; i++)
{
cin>>a[i].x>>a[i].y;
a[i].p=i;
}
sort(a+1,a+1+n,cmp2);
int len=1,pos=1;
dp[1]=a[1].y;
//path[1]=a[1].p;
path[1]=1;
for(int i=2; i<=n; i++)
{
if(a[i].y>dp[len])
{
dp[++len]=a[i].y;
path[i]=len;
}
else
{
pos=lower_bound(dp+1,dp+len+1,a[i].y)-dp;
{
dp[pos]=a[i].y;
path[i]=pos;
}
}
}
cout<<len<<endl;
for(int i=n; i>=1; i--)
{
if(path[i]==len)
{
cout<<a[i].p;
if(len!=1)
cout<<" ";
len--;
}
}
cout<<endl;
}
return 0;
}