版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82219813
【比赛链接】
【题解链接】
**【A】**Game Shopping
【思路要点】
- 按照题意模拟。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
int a[MAXN], b[MAXN];
int main() {
int n, m; read(n), read(m);
for (int i = 1; i <= n; i++)
read(a[i]);
for (int i = 1; i <= m; i++)
read(b[i]);
int ans = 0, pos = 1;
for (int i = 1; i <= n && pos <= m; i++)
if (b[pos] >= a[i]) {
pos++;
ans++;
}
writeln(ans);
return 0;
}
**【B】**Minimum Ternary String
【思路要点】
- 题目中 和 的相对位置始终不会发生改变,可以看做 可以自由移动, 和 留在原地。
- 将所有 插入到第一个 之前即可,若没有出现 ,则插到字符串末尾。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
char s[MAXN];
int main() {
scanf("%s", s + 1);
int n = strlen(s + 1), cnt = 0;
for (int i = 1; i <= n; i++)
if (s[i] == '1') cnt++;
for (int i = 1; i <= n; i++)
if (s[i] != '1') {
if (s[i] == '0') putchar(s[i]);
else {
if (cnt > 0) while (cnt--) putchar('1');
putchar(s[i]);
}
}
if (cnt > 0) while (cnt--) putchar('1');
return 0;
}
**【C】**Annoying Present
【思路要点】
- 使平均数最大即为使总和最大,若 ,则选择在 号位置操作,否则在中间位置操作即可。
- 中间量可能很大,需要 。
- 时间复杂度 。
【代码】
扫描二维码关注公众号,回复:
3029252 查看本文章
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
int n, m; long double ans;
long long calc(int x, int y) {
int len = y - x + 1;
return 1ll * (x + y) * len / 2;
}
int main() {
read(n), read(m);
for (int i = 1; i <= m; i++) {
int x, d; read(x), read(d);
ans += x * n;
if (d >= 0) ans += d * calc(0, n - 1);
else {
if (n & 1) ans += 2 * d * calc(0, n / 2);
else ans += d * (calc(0, n / 2) + calc(0, n / 2 - 1));
}
}
printf("%.10Lf\n", ans / n);
return 0;
}
**【D】**Relatively Prime Graph
【思路要点】
- 特判图不可能联通的情况,剩余部分暴力即可。
- 由于 ,我们至多搜索 个点对就可以找到答案。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
int gcd(int x, int y) {
if (y == 0) return x;
else return gcd(y, x % y);
}
int tot, x[MAXN], y[MAXN];
int main() {
int n, m; read(n), read(m);
if (m < n - 1) {
printf("Impossible\n");
return 0;
}
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (gcd(i, j) == 1) {
tot++; x[tot] = i, y[tot] = j;
if (tot == m) {
printf("Possible\n");
for (int k = 1; k <= m; k++)
printf("%d %d\n", x[k], y[k]);
return 0;
}
}
printf("Impossible\n");
return 0;
}
**【E】**Intercity Travelling
【思路要点】
- 分开考虑每一个 的贡献, 在第 段路程被计算了 次,在第 至 段每一段被计算了 次。
- 因此
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
const int P = 998244353;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
int power(int x, int y) {
if (y == 0) return 1;
int tmp = power(x, y / 2);
if (y % 2 == 0) return 1ll * tmp * tmp % P;
else return 1ll * tmp * tmp % P * x % P;
}
int bit[MAXN];
int main() {
int n; read(n);
bit[0] = 1;
for (int i = 1; i <= n; i++)
bit[i] = bit[i - 1] * 2 % P;
int ans = 0;
for (int i = 1; i <= n; i++) {
int x; read(x);
ans = (ans + 1ll * x * bit[n - i]) % P;
if (i != n) ans = (ans + 1ll * x * bit[n - i - 1] % P * (n - i)) % P;
}
writeln(ans);
return 0;
}
**【F】**Dominant Indices
【思路要点】
- 用线段树合并算出每一个节点 的 ,并维护区间最大值以便查询即可。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
const int MAXP = 2.5e7 + 5;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
struct SegmentTree {
struct Node {
int lc, rc;
int Max;
} a[MAXP];
int size, n;
void init(int x) {
n = x;
size = 0;
}
void update(int root) {
a[root].Max = max(a[a[root].lc].Max, a[a[root].rc].Max);
}
int modify(int root, int l, int r, int val) {
int ans = ++size;
a[ans] = a[root];
if (l == r) {
a[ans].Max++;
return ans;
}
int mid = (l + r) / 2;
if (mid >= val) a[ans].lc = modify(a[root].lc, l, mid, val);
else a[ans].rc = modify(a[root].rc, mid + 1, r, val);
update(ans);
return ans;
}
int modify(int root, int val) {
return modify(root, 1, n, val);
}
int merge(int ra, int rb, int l, int r) {
if (ra == 0 || rb == 0) return ra + rb;
if (l == r) {
a[ra].Max += a[rb].Max;
return ra;
}
int mid = (l + r) / 2;
a[ra].lc = merge(a[ra].lc, a[rb].lc, l, mid);
a[ra].rc = merge(a[ra].rc, a[rb].rc, mid + 1, r);
update(ra);
return ra;
}
int merge(int ra, int rb) {
return merge(ra, rb, 1, n);
}
int query(int root, int l, int r) {
if (l == r) return l;
int mid = (l + r) / 2;
if (a[root].Max == a[a[root].lc].Max) return query(a[root].lc, l, mid);
else return query(a[root].rc, mid + 1, r);
}
int query(int root) {
return query(root, 1, n);
}
} ST;
int n, ans[MAXN], root[MAXN];
vector <int> a[MAXN];
void dfs(int pos, int fa, int depth) {
root[pos] = ST.modify(root[pos], depth);
for (unsigned i = 0; i < a[pos].size(); i++)
if (a[pos][i] != fa) {
dfs(a[pos][i], pos, depth + 1);
root[pos] = ST.merge(root[pos], root[a[pos][i]]);
}
ans[pos] = ST.query(root[pos]) - depth;
}
int main() {
read(n);
ST.init(n);
for (int i = 1; i <= n - 1; i++) {
int x, y; read(x), read(y);
a[x].push_back(y);
a[y].push_back(x);
}
dfs(1, 0, 1);
for (int i = 1; i <= n; i++)
writeln(ans[i]);
return 0;
}
**【G】**Allowed Letters
【思路要点】
- 检查是否存在合法解实际上就是检查二分图是否存在完美匹配。
- 考虑 定理,由于二分图一侧的点数很小 ,我们可以直接暴力套用 定理来检验是否存在合法解。
- 强制匹配一条边后检验是否存在完美匹配是 的。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int MAXS = 1 << 6;
const int MAXC = 7;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
char s[MAXN];
int n, m, goal, bit[MAXC], a[MAXN], cnt[MAXS], sum[MAXS];
bool tryans(int bit, int pos) {
for (int i = 0; i <= goal; i++) {
if (i & bit) cnt[i]--;
if (i & a[pos]) sum[i]--;
}
for (int j = 0; j <= goal; j++) {
if (cnt[j] > sum[j]) {
for (int i = 0; i <= goal; i++) {
if (i & bit) cnt[i]++;
if (i & a[pos]) sum[i]++;
}
return false;
}
}
return true;
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1), read(m);
for (int i = 1; i <= 6; i++)
bit[i] = 1 << (i - 1);
goal = (1 << 6) - 1;
for (int i = 1; i <= n; i++)
a[i] = goal;
for (int i = 1; i <= m; i++) {
int pos; char tmp[15];
scanf("%d %s", &pos, tmp + 1);
int len = strlen(tmp + 1), tans = 0;
for (int j = 1; j <= len; j++)
tans += bit[tmp[j] - 'a' + 1];
a[pos] = tans;
}
for (int i = 1; i <= n; i++) {
int tmp = bit[s[i] - 'a' + 1];
for (int j = 0; j <= goal; j++) {
if (j & tmp) cnt[j]++;
if (j & a[i]) sum[j]++;
}
}
for (int i = 0; i <= goal; i++)
if (cnt[i] > sum[i]) {
printf("Impossible\n");
return 0;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 6; j++)
if ((a[i] & bit[j]) != 0 && tryans(bit[j], i)) {
putchar('a' + j - 1);
break;
}
}
printf("\n");
return 0;
}