l i n k link link:添加链接描述
问题在于如何区别
t
y
p
e
2
,
3
type2,3
type2,3
考虑我们如何确定一个元素是否属于最长
包含
i
i
i的前缀最长为
f
i
f_i
fi 后缀为
g
i
g_i
gi
那么当且仅当
f
i
+
g
i
=
r
e
s
+
1
f_i+g_i=res+1
fi+gi=res+1
考虑如果一个元素不在所有的元素里
那么删除了他之后答案不变 也就仍然存在…
我们考虑一个不包含
i
i
i 的同长序列
发现第
f
i
f_i
fi 个元素的
f
、
g
f、g
f、g 值相同
讨论一下发现充要 m a p map map 存一下就好
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
int rd() {
int sum = 0;char c = getchar();bool flag = true;
while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
if(flag) return sum;
else return -sum;
}
unordered_map<int,int>h;
int n;
int a[101000],b[101000];
void init() {
n = rd();
rep(i,1,n) a[i] = rd(),b[i] = a[i];
sort(a+1,a+n+1);
int l = 1,r = 1,cnt=0;
while(l <= n) {
while(a[r+1]==a[l]) r++;
h[a[l]] = ++cnt;
l = r+1;
}
rep(i,1,n) a[i] = h[b[i]];
return;
}
int f[101000];//f[i]->min number length of i
int ff[2][101000];//向前向后最长
int res;
void work() {
f[0] = 0;rep(i,1,n) f[i] = 1e9;
int l , r , m , k;
rep(i,1,n) {
l = 0;r = n;
while(l + 1 < r) {
m = (l+r)>>1;
if(f[m] < a[i]) l = m;
else r = m-1;
}
if(f[r] < a[i]) k = r;
else k = l;
ff[0][i] = k+1;
if(a[i] < f[k+1]) f[k+1] = a[i];
}
repp(i,n,1) if(f[i] != 1e9) {res = i;break;}
f[0] = 1e9; rep(i,1,n) f[i] = 0;
repp(i,n,1) {
l = 0; r = n;
while(l + 1 < r) {
m = (l+r)>>1;
if(f[m] > a[i]) l = m;
else r = m-1;
}
if(f[r] > a[i]) k = r;
else k = l;
ff[1][i] = k+1;
if(a[i] > f[k+1]) f[k+1] = a[i];
}
return;
}
unordered_map<int,int>num;
void solve() {
rep(i,1,n) if(ff[0][i] + ff[1][i] == res + 1) num[ff[0][i]]++;
rep(i,1,n) {
if(ff[0][i] + ff[1][i] == res + 1) {
if(num[ff[0][i]] == 1) printf("3");
else printf("2");
}
else printf("1");
}
return;
}
int main() {
init();
work();
solve();
return 0;
}