Atcoder B.C.302与R.C.163 (我的复健)メモ
去年下半年工作特忙,和今年前半年也没怎么搞算法,就上班做些常规的工作。
今天周末比较闲,阴天也不太想远走旅行,遂下午预约了个台球练习练习。突然想起来不知道今天有没有Atcoder的比赛,一查21:00有一场。一年多没打了,拿起来找找感觉呗,闲着也是闲着。工作都在写Java,写C++和Python都有点生疏了。
B.C.302 (AtCoder Beginner Contest 308)
A题,简单到写不出题解,题目给三个条件,全符合这三个条件的输入就给输出Yes,否则输出No。
N=8 a=list(map(int,input().split(" "))) t1 = all(map(lambda x: 100 <=x and x <= 675,a)) t2 = all(map(lambda x: x%25 ==0,a)) b = [] for i in range(N): b.append(a[i]) b.sort() Tflag = t1 and t2 for it in zip(a,b): if( it[0] != it[1]): Tflag = False break print("Yes" if Tflag else "No")
B题也是模拟,用个map(Python里的dict),单次检索时间\( O(\log(M)) \) ,总复杂度 \( O(N \log(M)) \)。此题由于数据量不大,据说直接存数组以\( O(MN) \) 的时间也能过
N,M = map(int,input().split(" ")) eat = input().split(" ") menu = input().split(" ") priceList =list(map(int, input().split(" "))) priceKey = {} for i in range(M): priceKey[menu[i]] = priceList[i+1] cost = 0 for it in eat: if it in priceKey: cost += priceKey[it] else: cost += priceList[0] print(cost)
C题注意两个点,一个是\( 10^{9} \)的数据量由于要相乘,所以数据需要定义成int64类型的。另一个排序是稳定排序,algorithm库中有个稳定排序std::stable_sort
。由于 std::sort
是不稳定排序,用错了就有几个测试点会坏。
include <cstdio> #include <algorithm> const int MAXN = 200007; struct node { int id; // = num/den long long num; long long den; bool operator<(const node &o) const { return num*o.den > den * o.num; } }; struct node a[MAXN]; int main(void){ int N; scanf("%d",&N); long long num,den; for(int i=0;i<N;++i){ scanf("%lld%lld",&num,&den); a[i].id = i+1; a[i].num = num; a[i].den = den + num; } std::stable_sort(a,a+N); for(int i=0;i<N;++i){ if(i>0) printf(" "); printf("%d",a[i].id); } printf("\n"); return 0; }
D. 基本的DFS
代码晚上回去写
E.
R.C. 163 (AtCoder Regular Contest 163)
A.看给出的单词是否切分成按严格字典序来排。最小要求切分两个元素,那么就极限法,就切两个,从哪儿切呢,首先第1个字母必是第1个单词的首字母,只要在其后存在比第1个单词的首字母更大的,就从这儿切分,就必然可以组成长度为2的符合字典序的列表。所以问题变成从第2个字母到最末字母查找是否存在比第1个字母的字典序更大的字母,存在则直接输出Yes,否则No
import java.io.BufferedReader; import java.io.InputStreamReader; class Main { public static void main() throws Exception { BufferedReader bf; bf = new BufferedReader(new InputStreamReader(System.in)); int T = Integer.parseInt(bf.readLine()); while (T-- > 0) { int N; N = Integer.parseInt(bf.readLine()); String msg = bf.readLine(); solve(N, msg); } return; } private static void solve(int N, String msg) { for (int i = 1; i < N; i++) { if (msg.charAt(i) > msg.charAt(0)) { System.out.println("Yes"); return; } } System.out.println("No"); return; } }
B. 给出一个序列\( {A_i} \)和正整数M。每次操作可以使\( A_i \) 中的一个元素+1
或-1
,使至少有M个\(A_i , (3 \le i \le N \),满足\(A_1 \le A_i \le A_2\)。求最小的操作次数。
由于\(A_1\)和\(A_2\)也是\( \{A_i\} \),如果\( \{A_i\} , 3 \le i \le N\)中各不相同,则操作哪个的次数都一样。如果 \( \{A_i\} ( 3 \le i \le N )\)中有相同的数字,则使\(A_1\)减小或\(A_2\)增加,相比与操作 \( \{A_i\} , 3 \le i \le N\)相同的数字的次数必然要少。于是可以将问题化为 将 \{A_i\} 排序得到 \{B_i\} 有 \{B_1,B_2, \cdots, B_{i},A_1,\cdots, A_2, B_{j},\cdots,B_N\} ,并随着A_1于是问题可以变为将\( \{A_i\} , 3 \le i \le N\)排序得到\(\{B_1,B_2,\cdots,B_{N-2}\}\),从中搜每个长为M的区间,计算使\(A_1,A_2\)到这个区间的最小操作次数。复杂度为\(O(N \log N) + O (N) = O( N \log N ) \) -1
与A2+1
的操作,使A_1与A_2之间的数字有至少M个。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; class Main { public static void main() throws Exception { BufferedReader bf; bf = new BufferedReader(new InputStreamReader(System.in)); String[] line = bf.readLine().split(" "); int N = Integer.parseInt(line[0]); int M = Integer.parseInt(line[1]); int[] arr = Arrays.stream(bf.readLine().split(" ")).mapToInt(Integer::parseInt).toArray(); int lwbd = arr[0]; int upbd = arr[1]; int[] b = Arrays.copyOfRange(arr, 2, N); Arrays.sort(b); int minOp = 0x7FFFFFFF; for (int i = 0; i < N - 1 - M; i++) { minOp = Math.min(minOp, Math.max(0, lwbd - b[i]) + Math.max(0, b[i + M - 1] - upbd)); } System.out.println(minOp); return; } }
C.调和级数