codeforces 486E. LIS of Sequence

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 fg 值相同

讨论一下发现充要 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; 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值