Codeforces #669 div2

A

对于0就不管,对于连续的两个1也不管,对于单个的1,直接删除,显然删除元素少于 \(\frac{n}{2}\)

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e3+10;

ll N, T, val[MAXN];

int main() {
	scanf("%lld", &T);
	while (T--) {
		scanf("%lld", &N);
		ll sum = 0;
		memset(val, 0, sizeof(val));
		for (ll i = 1; i <= N; i++) {
			scanf("%lld", &val[i]);
		}
		for (ll i = 1; i <= N; i++) {
			if (val[i]) {
				if (val[i] && val[i+1]) {i++;continue;}
				else sum++;
			}
		}
		printf("%lld\n", N - abs(sum));
		for (ll i = 1; i <= N; i++) {
			if (!val[i]) {
				printf("%lld ", val[i]);
			} else {
				if (val[i] && val[i+1]) {
					printf("%lld %lld ", val[i], val[i+1]);
					i++;	
				}
			}
		}
		printf("\n");
	}
	return 0;
}

/*
2
12
1 0 1 0 1 1 1 1 1 0 1 1
14
1 0 1 1 1 1 1 1 1 1 0 1 1 1
*/

B

直接让最大的数放前面,然后把和前面 gcd 最大的数放前面即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e3+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;

ll N, T, a[MAXN], g[MAXN][MAXN], b[MAXN], vis[MAXN];

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);	
}

bool cmp(ll a, ll b) {
	return a > b;	
}

int main() {
	scanf("%lld", &T);
	while (T--) {
		scanf("%lld", &N);
		for (ll i = 1; i <= N; i++) {
			scanf("%lld", a+i);
		}
		sort(a+1, a+N+1, cmp);
		ll now = 0;
		memset(vis, 0, sizeof(vis));
		for (ll i = 1; i <= N; i++) {
			ll maxn = -INF, maxi = 0;
			for (ll j = 1; j <= N; j++) {
				if (vis[j]) continue;
				if (gcd(a[j], now) > maxn) {
					maxn = gcd(a[j], now);
					maxi = j;
				}
			}
			b[i] = a[maxi];
			now = gcd(a[maxi], now);
			vis[maxi] = 1;
		}
		for (ll i = 1; i <= N; i++) {
			printf("%lld ", b[i]);	
		}
		printf("\n");
	}
	return 0;
}

/*
1
6
6 2 8 2 68 9
*/

C

对于一次询问
如果 \(a > b\)\(b \mod a > a \mod b\)
如果 \(b > a\)\(b \mod a < a \mod b\)
那么每次更新最大值,然后直接填小的那个数,显然 \(2 * n - 1\) 次内能完成
最后把剩下一个位置放 \(n\) 就可以了

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 2e5+10;

ll N, M, val[MAXN], vis[MAXN];

int main() {
	cin >> N;
		ll mx = 1;
		for (ll i = 2; i <= N; i++) {
			ll x, y;
			cout << "? " << mx << " " << i << endl;
			cin >> x;
			cout << "? " << i << " " << mx << endl;
			cin >> y;
			if (x > y) {
				val[mx] = x;
				mx = i;
			} else {
				val[i] = y;
			}
		}
		val[mx] = N;
		cout << "! ";
		for (ll i = 1; i <= N; i++) {
			cout << val[i] << " ";
		}
		cout << endl;
		cout.flush();
	return 0;
}

D

维护一下
左边第一个大于 \(h_i\) 的数字
左边第一个小于 \(h_i\) 的数字
右边第一个大于 \(h_i\) 的数字
右边第一个小于 \(h_i\) 的数字
上面四个用单调栈搞一下。
然后直接转移就行了
时间复杂度 \(O(n)\)

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const ll MAXN = 3e5+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;

ll N, M, f[MAXN], val[MAXN], lle[MAXN], lge[MAXN], rle[MAXN], rge[MAXN];
vector <pair<ll, ll> > st;
vector <ll> jp[MAXN];

int main() {
	scanf("%lld", &N);
	memset(f, 0x3f, sizeof(f));
	for (ll i = 1; i <= N; i++) {
		scanf("%lld", val+i);
		f[i] = INF;
	}
	f[1] = 0;
	for (ll i = 1; i <= N; i++) {
		while (!st.empty() && st.back().first > val[i]) st.pop_back();
		if (st.empty()) lle[i] = -1;
		else lle[i] = st.back().second;
		st.push_back({val[i], i});
	}
	st.clear();
	for (ll i = 1; i <= N; i++) {
		while (!st.empty() && st.back().first < val[i]) st.pop_back();
		if (st.empty()) lge[i] = -1;
		else lge[i] = st.back().second;
		st.push_back({val[i], i});
	}
	st.clear();
	for (ll i = N; i >= 1; i--) {
		while (!st.empty() && st.back().first > val[i]) st.pop_back();
		if (st.empty()) rle[i] = -1;
		else rle[i] = st.back().second;
		st.push_back({val[i], i});
	}
	st.clear();
	for (ll i = N; i >= 1; i--) {
		while (!st.empty() && st.back().first < val[i]) st.pop_back();
		if (st.empty()) rge[i] = -1;
		else rge[i] = st.back().second;
		st.push_back({val[i], i});
	}
	for (ll i = 1; i <= N; i++) {
		if (rle[i] != -1) jp[i].push_back(rle[i]);
		if (rge[i] != -1) jp[i].push_back(rge[i]);
		if (lle[i] != -1) jp[lle[i]].push_back(i);
		if (lge[i] != -1) jp[lge[i]].push_back(i);
	}
	for (ll i = 1; i <= N; i++) {
		for (unsigned int j = 0; j < jp[i].size(); j++) {
			f[jp[i][j]] = min(f[jp[i][j]], f[i] + 1);
		}
	}
	printf("%lld\n", f[N]);
	return 0;
}
posted @ 2020-09-13 22:37  Gensokyo_Alice  阅读(122)  评论(0编辑  收藏  举报