题意:
n(10^5)个数字的序列a 求每个位置i 它是不出现在任何LIS中 还是 出现在一些LIS中 还是 出现在所有LIS中
思路:
比赛时候唯一没做出的题… 赛后还是不会做… - -b 看了别人的代码觉得好精妙!!
首先以O(nlogn)复杂度求出LIS
然后我们倒序扫描序列a 对于位置i 如果lis[i]=LIS或者a[i]<big[lis[i]+1] (big[x]表示lis=x的a的最大值 这里的意思是 如果a[i]是某个LIS的最后一个 或者 能与某个LIS想接) 那么这个位置是出现在LIS中的 它是不是必经之路呢?? 我们在记录一个num[y] 表示lis=y的且出现在LIS中的位置的个数
最后 我们判断如果不出现在LIS中则分到1组 否则 如果num[lis[i]]=1说明它是毕竟之路(没有与它并列的位置) 分到3组 否则 到2组
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 100010
int n;
int a[N], lis[N], st[N], top, in[N], big[N], num[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
top = 1;
for (int i = 1; i <= n; i++) {
if (st[top - 1] < a[i]) {
st[top] = a[i];
lis[i] = top;
top++;
} else {
int pos = lower_bound(st + 1, st + top, a[i]) - st;
st[pos] = a[i];
lis[i] = pos;
}
}
top--;
for (int i = n; i >= 1; i--) {
if (lis[i] == top || big[lis[i] + 1] > a[i]) {
in[i] = 1;
num[lis[i]]++;
big[lis[i]] = max(big[lis[i]], a[i]);
}
}
for (int i = 1; i <= n; i++) {
if (in[i]) {
if (num[lis[i]] > 1)
putchar('2');
else
putchar('3');
} else
putchar('1');
}
return 0;
}