本期题比上期更简单,只有一个绿题,而且并不是很难的数学题,估计比赛时能AK
C - ABC Tournament
模拟,记录一下位置
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def main():
items = sys.version.split()
fp = open("in.txt") if items[0] == "3.10.6" else sys.stdin
n = int(fp.readline())
a = list(map(int, fp.readline().split()))
ans = -1
lt = [i for i in range(len(a))]
for i in range(n):
t = []
m = len(lt)
for j in range(m // 2):
i0, i1 = j * 2, j * 2 + 1
if a[lt[i0]] > a[lt[i1]]:
t.append(lt[i0])
else:
t.append(lt[i1])
if len(lt) == 2:
ans = lt[0] if a[lt[0]] < a[lt[1]] else lt[1]
lt = t
print(ans + 1)
if __name__ == "__main__":
main()
D - Snuke Prime
模拟题,我的思路是边界和中间的区间单独计算
# -******- coding: utf-8 -******-
# @time : 2023/12/28 20:10
# @author : c.d.
# @desc :
# @file : atcoder.py
# @software : PyCharm
import sys
from collections import defaultdict
def main():
items = sys.version.split()
fp = open("in.txt") if items[0] == "3.10.9" else sys.stdin
n, m = map(int, fp.readline().split())
arr = defaultdict(list)
for i in range(n):
a, b, c = map(int, fp.readline().split())
arr[a].append((0, c))
arr[b].append((1, c))
keys = list(arr.keys())
keys.sort()
cur = 0
ans = 0
last = -1
for k in keys:
if last != -1 and k - last > 1:
ans += min(cur, m) * (k - last - 1)
drop = 0
for op, v in arr[k]:
if op == 0:
cur += v
else:
drop += v
ans += min(cur, m)
cur -= drop
last = k
print(ans)
if __name__ == "__main__":
main()
E - Peddler
有拓扑性质的题目,容易想到DP
记录一个在该点买入后的最大值和卖出后的最大值,
答案是遍历卖出后的最大值。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <algorithm>
#define LT(x) (x * 2)
#define RT(x) (x * 2 + 1)
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi;
int n, m;
LL a[200020];
vi g[200020];
LL dp[200020][2];
int main() {
//freopen("in.txt", "r", stdin);
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i)
scanf("%lld", a + i);
for (int i = 0; i < m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
u--, v--;
g[v].push_back(u);
}
for (int i = 0; i < n; ++i)
dp[i][1] = INT_MIN;
LL ans = INT_MIN;
for (int i = 0; i < n; ++i) {
dp[i][0] = -a[i];
for (int v : g[i]) {
if (dp[v][0] + a[i] > dp[i][1]) {
dp[i][1] = dp[v][0] + a[i];
}
if (dp[v][0] > dp[i][0])
dp[i][0] = dp[v][0];
}
ans = max(ans, dp[i][1]);
}
printf("%lld\n", ans);
return 0;
}
F - +1-1x2
数学题
正难则反
从y倒推x,详情见代码
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <algorithm>
#define LT(x) (x * 2)
#define RT(x) (x * 2 + 1)
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi;
LL x, y;
map<LL, LL> cnt;
LL get(LL a) {
if (cnt.count(a))
return cnt[a];
if (a <= x)
return x - a;
LL ret = a - x;
if (a & 1) {
ret = min(ret, get((a + 1) / 2) + 2);
ret = min(ret, get((a - 1) / 2) + 2);
}
else {
ret = min(ret, get(a / 2) + 1);
}
return cnt[a] = ret;
}
int main() {
//freopen("in.txt", "r", stdin);
scanf("%lld%lld", &x, &y);
if (x >= y) {
printf("%lld\n", x - y);
}
else {
LL ans = get(y);
printf("%lld\n", ans);
}
return 0;
}