Codeforces #669 div2
阿新 • • 發佈:2020-09-13
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;
}