比赛 2022级DP专题练习赛7 评测结果 AAAWWAAAAAAAAAAAAAAA
题目名称 数列 最终得分 90
用户昵称 zxhhh 运行时间 2.730 s
代码语言 C++ 内存使用 17.36 MiB
提交时间 2023-02-27 20:59:23
显示代码纯文本
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5, mod = 1e9 + 7;
typedef long long ll;

int s[N << 1], n, dp[N << 1], t[N << 1], ord[N << 1];
ll cnt, ans, tw[N], c[N <<1];

struct node {
	int l, r, m;
	ll c;
}nodes[N << 2];

inline void push_up (int p) {
	nodes[p].m = max(nodes[p << 1].m, nodes[p << 1 | 1].m);
	nodes[p].c = 0;
	if (nodes[p << 1].m >= nodes[p].m) nodes[p].c = (nodes[p].c+nodes[p << 1].c) % mod;
	if (nodes[p << 1 | 1].m >= nodes[p].m) nodes[p].c = (nodes[p].c + nodes[p << 1 | 1].c) % mod;
}

void build (int p, int l, int r) {
	nodes[p].l = l, nodes[p].r = r;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build (p << 1, l, mid); build (p << 1 | 1, mid +1, r);
	push_up (p);
}

void reset (int p, int idx, int m, ll c) {
	if (idx == 0) return;
	int tl = nodes[p].l, tr = nodes[p].r;
	if (tl == tr) {
		if (nodes[p].m < m) nodes[p].m = m, nodes[p].c = c;
		else if (nodes[p].m == m) nodes[p].c = (nodes[p].c + c) % mod;
		return;
	}
	int mid = (tl + tr) >> 1;
	if (idx <= mid) reset (p << 1, idx, m, c);
	else reset (p << 1 | 1, idx, m, c);
	push_up (p);
} 

node query (int p, int l, int r) {
	int tl = nodes[p].l, tr = nodes[p].r;
	if (tl >= l && tr <= r) return nodes[p];
	int mid = (tl + tr) >> 1; node res; res.m = res.c = 0;
	if (l <= mid) {
		node k = query(p << 1, l, r);
		if(res.m < k.m) res.m = k.m, res.c = k.c;
		else if (res.m == k.m) res.c = (res.c + k.c) % mod;
	}
	if (r > mid) {
		node k = query(p << 1 | 1, l, r);
		if(res.m < k.m) res.m = k.m, res.c = k.c;
		else if (res.m == k.m) res.c = (res.c + k.c) % mod;
	}
	return res;
}

//deque <int> q;
//vector <int> f[N];
//
//void dfs (int p) {
//	if (p > n) {
////		cout <<endl;
//		memset(dp, 0, sizeof(dp)); memset(c, 0, sizeof(c));
//		int m = 0;
//		deque <int> t = q;
//		for (int i = 1;i <= n;i++) a[i] = t.front(), t.pop_front();
//		for (int i = 1;i <= n;i++) {
//			int x = 0;
//			for (int j = 1;j < i;j++) {
//				if (a[j] < a[i]) {
//					if (dp[j] > x) {
//						c[i] = c[j];
//						x = dp[j];
//					}
//					else if (dp[j] == x) c[i] += c[j];
//				} 
//			}
//			dp[i] = x + 1;
//			if (dp[i] == 1) c[i] = 1;
//			m = max(dp[i], m);
////			cout << dp[i] << " " <<c[i] <<endl;
//		}
//		if (m < ans) return;
//		if (m > ans) cnt = 0, ans = m;
//		for (int i = 1;i <= n;i++) if (dp[i] == m) cnt += c[i], cnt %= mod;
//		return;
//	}
//	q.push_front(s[p]); dfs(p + 1); q.pop_front();
//	if (p > 1) {q.push_back(s[p]); dfs(p + 1); q.pop_back(); }
//}
//
int main () {
	freopen("lisshulie.in", "r", stdin);
	freopen("lisshulie.out", "w", stdout);
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) scanf("%d", &s[i]);
	reverse(s + 1, s + 1 + n);
	for (int i = n + 1;i <= 2 * n;i++) s[i] = s[2 * n + 1 - i];
	tw[0] = 1;
	for (int i = 1;i <= n;i++) tw[i] = tw[i - 1] * 2 % mod;
	for (int i = 1;i <= 2 * n;i++) t[i] = s[i];
	sort(t +1, t + 1 + 2 *n);
	int ss = unique (t +1, t + 1 + 2 * n) - t - 1; 
	for (int i = 1;i <= 2 * n;i++) ord[i] = lower_bound (t+1, t+1+ss, s[i]) - t;
	build (1, 1, n);
	for (int i = 1;i <= 2 * n;i++) {
		node x = query(1, 1, ord[i] - 1);
		dp[i] = x.m + 1;
		if(dp[i] >1) c[i] = x.c; 
		else c[i] = 1;
		reset (1, ord[i], dp[i], c[i]);
	}
	for (int i = 1;i <= 2 * n;i++) {
//		cout << ord[i] << " " << dp[i] << " " <<c[i] << endl;
		if(dp[i] > ans ) ans = dp[i], cnt = c[i];
		else if (dp[i] == ans) cnt = (cnt + c[i]) % mod;
	}
	if (ans < n) cnt = cnt * tw[n - ans - 1] % mod;
	cout << ans <<" " << cnt << endl;
//	dfs(1);
//	cout << ans << " " << cnt << endl;
	return 0;
}