https://codeforces.com/contest/1993
A. Question Marks
解析:简单题,略
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
typedef long long LL;
//#define int LL
#define ld long double
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 998244353;
const ld eps = 1e-12;
const int N = 1e5 + 10, M = 1e6 + 10;
int n;
char s[N];
signed main() {
int T;
cin >> T;
while (T--) {
cin >> n;
scanf("%s", s + 1);
int A, B, C, D;
A = B = C = D = 0;
for (int i = 1; i <= 4*n; i++) {
if (s[i] == 'A') {
A++;
}
else if (s[i] == 'B') {
B++;
}
else if (s[i] == 'C') {
C++;
}
else if (s[i] == 'D') {
D++;
}
}
int ans = 0;
ans += min(A, n);
ans += min(B, n);
ans += min(C, n);
ans += min(D, n);
printf("%d\n", ans);
}
return 0;
}
B. Parity and Sum
解析:简单题,略
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
typedef long long LL;
#define int LL
#define ld long double
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 998244353;
const ld eps = 1e-12;
const int N = 2e5 + 10, M = 1e6 + 10;
int n;
bool cmp(const int& a, const int& b) {
return a > b;
}
signed main() {
int T;
cin >> T;
while (T--) {
cin >> n;
vector<int>e, o;
e.reserve(n + 10), o.reserve(n + 10);
for (int i = 1; i <= n; i++) {
int a;
scanf("%lld", &a);
if (a % 2) {
o.push_back(a);
}
else {
e.push_back(a);
}
}
sort(o.begin(), o.end());
sort(e.begin(), e.end(),cmp);
if (o.size() == 0 || e.size() == 0) {
cout << 0 << endl;
continue;
}
int mx = o[o.size() - 1];
int ans1 = 0;
for (int i = 0; i < e.size(); i++) {
do {
mx = mx + e[i];
ans1++;
} while (mx - e[i] < e[i]);
//cout << "__________" << mx << " " << e[i] << endl;
//e[i] = mx;
}
sort(e.begin(), e.end());
mx = o[o.size() - 1];
int ans2 = 0;
for (int i = 0; i < e.size(); i++) {
do {
mx = mx + e[i];
ans2++;
} while (mx - e[i] < e[i]);
//cout << "__________" << mx << " " << e[i] << endl;
//e[i] = mx;
}
printf("%lld\n", min(ans1, ans2));
}
return 0;
}
/*
7
5
1 3 5 7 9
4
1 4 10 20
3
2 3 4
4
3 2 2 8
6
4 3 6 1 2 1
6
3 6 1 2 1 2
5
999999996 999999997 999999998 999999999 1000000000
*/
C. Light Switches
解析:
易发现每个灯的状态都是以 2k 为周期变化的,要想所有等都亮,则需要所有的灯在某一个 (r,r-k+1) 的区间内都亮。
所以可以将所有的 ai 都 mod (2*k),再用双指针找到这个区间。
因为最终答案 s >=max(a) 的,所以
最终的答案 s=max+(r-max)%(2*m)
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
typedef long long LL;
//#define int LL
#define ld long double
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 998244353;
const ld eps = 1e-12;
const int N = 2e5 + 10, M = 1e6 + 10;
int n, m;
signed main() {
int T;
cin >> T;
while (T--) {
cin >> n >> m;
vector<int>d(4 * m+2, 0);
int mx = -1;
int p = 2 * m;
for (int i = 1; i <= n; i++) {
int a;
scanf("%d", &a);
d[a % p]++;
mx = max(mx, a);
}
for (int i = 0; i < 2*m; i++) {
d[i + p] = d[i];
}
int ans = -1, l = 0, cn = 0;
for (int i = 0; i <= 4 * m; i++) {
cn += d[i];
if (i - l >= m) {
cn -= d[l];
l++;
}
if (cn == n) {
ans = i;
break;
}
}
if (ans == -1) {
cout << -1 << endl;
continue;
}
//cout << "_______________" << ans << endl;
int s = mx + ((ans - mx) % p + p) % p;
cout << s << endl;
}
return 0;
}
/*
9
4 4
2 3 4 5
4 3
2 3 4 5
4 3
3 4 8 9
3 3
6 2 1
1 1
1
7 5
14 34 6 25 46 7 17
6 5
40 80 99 60 90 50
6 5
64 40 50 68 70 10
2 1
1 1000000000
*/
D. Med-imize
解析:二分+dp
使用一种不需要排序就能找到中位数的方法:
使用二分,每次判断mid是否是中位数,将数组ai>=mid的值标为1,否则标为-1,-1的个数等于1的个数时说明mid是中位数,形式地表示为sum=0时mid是中位数。
对于删除子数组操作使用dp处理:
f[i] 表示:前 i 个中剩余个数不超过 k 的最大sum。sum>=0表示mid可以更大,反之mid取的过大
注意到删除的子数组必须是连续的k个,所以:
f[i]=max(f[i-k],f[i-1]+b[i]);
又因为最后剩余的个数必须小于 k 个,所以:
if(i%k==0):f[i]=max(f[i-k],b[i]);
因为当 i%k==0 时,如果保留第 i 个和第 i-1 个,则此时前面还剩下 x 个,此时 x%k+2 一定会等于 k,不合题意。这个性质手写几个例子就能发现。
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
typedef long long LL;
//#define int LL
#define ld long double
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 998244353;
const ld eps = 1e-12;
const int N = 5e5 + 10, M = 1e6 + 10;
int n,k;
int A[N], b[N], f[N];
bool check(int mid) {
for (int i = 0; i < n; i++) {
if (mid <= A[i]) {
b[i] = 1;
}
else {
b[i] = -1;
}
}
f[0] = b[0];
for (int i = 1; i < n; i++) {
if (i % k == 0) {
f[i] = max(b[i], f[i - k]);
}
else {
f[i] = f[i - 1] + b[i];
if (i > k) {
f[i] = max(f[i], f[i - k]);
}
}
}
return f[n - 1] > 0;
}
signed main() {
int T;
cin >> T;
while (T--) {
scanf("%d%d", &n,&k);
int mx = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &A[i]);
mx = max(mx, A[i]);
}
int l = 0, r = mx, ret = l;
while (l <= r) {
int mid = l + (r - l) / 2;
if (check(mid)) {
ret=mid;
l=mid+1;
}
else {
r=mid-1;
}
}
printf("%d\n",ret);
}
return 0;
}
/*
5
4 3
3 9 9 2
5 3
3 2 5 6 4
7 1
5 9 2 6 5 4 6
8 2
7 1 2 6 8 3 4 5
4 5
3 4 5 6
*/