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;
}
希望我们都有一个光明的未来