Problem

让你求出LIS的长度,并且求出不同的LIS序列的交集(即必须被包含在LIS中的点)

Solution

我们求出正的LIS和倒着的,如果一个位置上,第一次的f值+f值减掉1(本身算了2次)等于LIS的长度,那么这个位置存在于LIS中
我们再对f[i]hash一下,如果只有1次,那么这个位置是必须被包含的

Notice

最后判断必须被包含很麻烦

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 100000;
const double eps = 1e-6, phi = acos(-1);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
int X1[N + 5], f1[N + 5], Q1[N + 5], X2[N + 5], f2[N + 5], Q2[N + 5], flag[N + 5];
int sqz()
{
	freopen("bubble.in", "r", stdin);
	freopen("bubble.out", "w", stdout);
	int n = read(), num1 = 1, num2 = 1;
	rep(i, 1, n) X1[i] = read();
	f1[1] = 1, Q1[0] = X1[1];
	rep(i, 2, n)
	{
		int t = lower_bound(Q1, Q1 + num1, X1[i]) - Q1;
		if (t < num1) Q1[t] = X1[i];
		else Q1[num1++] = X1[i];
		f1[i] = t + 1;
	}
	rep(i, 1, n) X2[i] = n + 1 - X1[n - i + 1];
	f2[n] = 1, Q2[0] = X2[1];
	rep(i, 2, n)
	{
		int t = lower_bound(Q2, Q2 + num2, X2[i]) - Q2;
		if (t < num2) Q2[t] = X2[i];
		else Q2[num2++] = X2[i];
		f2[n - i + 1] = t + 1;
	}
	write(num1); puts("");
	rep(i, 1, n) if (f1[i] + f2[i] == num1 + 1) flag[f1[i]]++;
	rep(i, 1, n) if (f1[i] + f2[i] == num1 + 1 && flag[f1[i]] == 1) printf("%d ", i);
	return 0;
}
posted on 2017-11-01 09:09  WizardCowboy  阅读(136)  评论(0编辑  收藏  举报