A 题意:给一组数,求两个不同的数的最大距离(保证至少有两个数不同)
最大的两个数位a[i]和a[j],至少有一个在两端。贪心即可
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (a[i] != a[0]) {
ans = max(ans, i - 0);
}
if (a[i] != a[n - 1]) {
ans = max(ans, n - 1 - i);
}
}
cout << ans << '\n';
return 0;
}
B:给定一些物品的高度。放进一个高度为h,宽度为2的箱子里(具体看题目描述吧,不知道怎么描述好),求最多放多少个
从大到小放就行。二分的话可以提高速度,但是题目的数据范围没必要
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, h;
cin >> n >> h;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int k = n; k >= 0; k--) {
vector<int> b(a.begin(), a.begin() + k);
sort(b.begin(), b.end());
long long sum = 0;
for (int i = (int) b.size() - 1; i >= 0; i -= 2) {
sum += b[i];
}
if (sum <= h) {
cout << k << '\n';
return 0;
}
}
return 0;
}
C:给定两个01矩阵,每次可以选择一个矩形来翻转它的四个顶点,求是否可以把左边的矩阵变为右边的矩阵
贪心,我也不知道怎么证明
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int h, w;
cin >> h >> w;
vector<vector<int>> a(h, vector<int>(w));
vector<vector<int>> b(h, vector<int>(w));
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
cin >> a[i][j];
}
}
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
cin >> b[i][j];
}
}
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (a[i][j] != b[i][j]) {
if (i == h - 1 || j == w - 1) {
cout << "No" << '\n';
return 0;
}
a[i][j] ^= 1;
a[i + 1][j] ^= 1;
a[i][j + 1] ^= 1;
a[i + 1][j + 1] ^= 1;
}
}
}
cout << "Yes" << '\n';
return 0;
}
D:直接看题目下的图吧,比较清楚。
做法:注意到答案只和R-L有关,先对s排序,注意到第i行出现的数字且不在第i+1行出现的个数为min(s[i+1]-s[i], r-l+1),
那么我们先求出s的差分数列,然后排序,求前缀和。对于每一次询问,对s的差分序列做二分,答案根据min(s[i+1]-s[i], r-l+1)可以分为两部分,前半部分的贡献可以通过前缀和求出来,后半部分直接乘一下即可。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 1.1e5;
int N;
ll S[MAXN];
ll pref[MAXN];
const int MAXQ = 1.1e5;
int Q;
int main() {
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N;
for (int i = 0; i < N; i++) cin >> S[i];
sort(S, S + N);
for (int i = 0; i+1 < N; i++) {
S[i] = S[i+1] - S[i];
}
// the differences
sort(S, S + N-1);
//for (int i = 0; i < N; i++) cout << S[i] << " "; cout << endl;
pref[0] = 0;
for (int i = 0; i < N-1; i++) {
pref[i+1] = pref[i] + S[i];
}
//for (int i = 0; i < N; i++) cout << pref[i] << " "; cout << endl;
cin >> Q;
for (int q = 0; q < Q; q++) {
ll L, R; cin >> L >> R;
ll W = R - L + 1;
ll ind = lower_bound(S, S + N - 1, W) - S;
cout << (N - ind) * W + pref[ind] << " \n"[q+1 == Q];
}
return 0;
}
E:给了一些长度为2^i的木棍,问最多可以组成多少个三角形
分析:只有两种三角形:(i, i, i) (i ,j, j) 其中i< j
贪心(我也不知道为啥是是正确的,官方有分析 https://codeforces.com/blog/entry/66411)
从小到大,先保证之前没用到的i,来组成(i, j, j),剩下的组成(j, j, j)
//贪心,每次拿剩下的还未匹配的先匹配(i, j, j) i < j,然后在匹配(j, j, j)
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 3.1e5;
int N;
ll A[MAXN];
int main() {
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N;
for (int i = 0; i < N; i++) cin >> A[i];
ll tot = 0;
ll carry = 0; // <= 3
for (int i = 0; i < N; i++) {
ll v = min(A[i] / 2, carry);
tot += v;
carry -= v;
A[i] -= 2 * v;
assert(A[i] <= 1 || carry == 0);
tot += A[i] / 3;
A[i] %= 3;
carry += A[i];
}
cout << tot << '\n';
return 0;
}
F G H题没去看。。AC的人数太少了。