Loading

Codeforces Contest 1380

A Three Indices

题意

给你一个 \(1-n\) 的排列 \(p\),让你找到三个数 \(i,j,k\) 使得 $p_i < p_j $ 且 \(p_j > p_k\)

解析

先从前往后扫一遍,求出哪些位置满足存在一个比它小的在它前面。这可以用树状数组统计当前 \(1-i\) 中出现了几个。

然后倒着在做一遍求出哪些位置存在一个比它小的在它后面。

找到一个都满足的点,然后在它前面和后面都找一个比它小的即可。

若不存在即为没有。

#include <bits/stdc++.h>
using namespace std;
int t;
int n;
int a[1010];
int c[1010];
bool mark[1010], ans;
int pos;
int lowbit(int x){return x & -x;}
void add(int x) {
	while (x <= n) {
		c[x]++;
		x += lowbit(x);
	}
}
int ask(int x) {
	int ret = 0;
	while (x) {
		ret += c[x];
		x -= lowbit(x);
	}
	return ret;
}
int main() {
	cin >> t;
	while (t--) {
		ans = 0;
		cin >> n;
		for (int i = 1; i <= n; i++) c[i] = 0, mark[i] = 0;
		for (int i = 1; i <= n; i++) cin >> a[i];
		for (int i = 1; i <= n; i++) {
			if (ask(a[i] - 1)) {
				mark[i] = 1;
			}
			add(a[i]);
		}
		for (int i = 1; i <= n; i++) c[i] = 0;
		for (int i = n; i; i--) {
			if (mark[i] && ask(a[i] - 1)) {
				pos = i;
				ans = 1;
				break;
			}
			add(a[i]);
		}
		if (ans) {
			puts("YES");
			for (int i = 1; i < pos; i++) {
				if (a[i] < a[pos]) {
					cout << i << " ";
					break;
				}
			}
			cout << pos << " ";
			for (int i = pos + 1; i <= n; i++) {
				if (a[i] < a[pos]) {
					cout << i << endl;
					break;
				}
			}
		} else puts("NO");
	}
	return 0;
}

D Berserk And Fireball

解析

我们先在 \(a\) 中找到 \(b\),把这些位置标记下来,如果找不到则无解。

然后对于每两个标记的数之间我们统计有多少个数(\(0\)号位和\(n+1\)号位视为被标记的)。

如果这个值小于 \(k\) 的话,我们只能 Berserk 把它们干掉,而如果这些数的最大值大于两端点标记的数的最大值则无解。所以我们还需记录这个最大值。

如果这个值大于 \(k\) 的话则一定有解。

分成两种情况:

1、\(y \times k < x\)

这种情况用 \(k\)Berserk 比用一次 Fireball 更优。

但是最后不用 Fireball 可能干不掉全部的,所以我们要特判这种情况。

如果最大值比两端点都要小,则不需要用 Fireball,一直用 Berserk 就行。

否则我们一定要用一次 Fireball 把最大的干掉。剩下的全部用 Berserk

2、\(y \times k \ge x\)

这种情况用 Fireball 更优,但是可能会出现剩余的情况,所以在用 Fireball 之前先用 Berserk 干到是 \(k\) 的倍数就行。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 200010;
ll n, m;
ll x, y, k;
ll a[N], b[N];
ll top = 1;
bool mark[N];
ll ans, cnt, mx;
int main() {
	cin >> n >> m;
	cin >> x >> k >> y;
	for (ll i = 1; i <= n; i++) cin >> a[i];
	for (ll i = 1; i <= m; i++) cin >> b[i];
	for (ll i = 1; i <= n; i++) {
		if (a[i] == b[top]) {
			mark[i] = 1;
			top++;
		}
	}
	if (top < m) puts("-1");
	else {
		int lst = 0;
		mark[n + 1] = 1;
		for (int i = 1; i <= n + 1; i++) {
			if (mark[i]) {
				cnt = i - lst - 1;
				if (cnt == 0) {
					lst = i;
					mx = 0;
					continue;
				}
				if (cnt < k) {
					if (mx < max(a[lst], a[i])) {
						ans += y * cnt; 
					} else {
						puts("-1");
						return 0;
					}
				} else {
					if (y * k < x) {
						if (mx < max(a[lst], a[i])) {
							ans += y * cnt;
						} else {
							ans += y * (cnt - k) + x;
						}
					} else {
						ans += cnt / k * x + (cnt % k) * y;
					}
				}
				lst = i;
				mx = 0;
			} else {
				mx = max(mx, a[i]);
			}
		}
		cout << ans;
	}
	return 0;
}
posted @ 2021-06-21 22:08  Semsue  阅读(36)  评论(0编辑  收藏  举报
Title