1. 程式人生 > 實用技巧 >Codeforces #669 div2

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;
}