AtCoder Beginner Contest 346
最刺激的一集。
尝试挑战手速极限,用了 57s 做 A。但是好像还是很慢。
然后做 B,仍然想挑战手速。结果一眼出思路只要把 wbwbwwbwbwbw
多重复几遍就可以代替「无限长」。
很快就写完了。然后交了三发罚时。后来发现我复制若干遍 wbwbwwbwbwbw
的时候好像复制错了/ll /ll
过 B 之前很快过掉了 C, D。其中 D 有一发罚时是因为 DP 的边界错了。
过了 A~D 后看 E。感觉没什么思路。但是想到了如果这一行/列被覆盖了多次,那么只有最后一次覆盖是有效的。
于是想先实现这个过程。发现如果要这么做,必然需要将所有操作倒序处理。于是就莫名奇妙地联想到了白雪皑皑,发现倒序处理是正确的。延续着涂色的思路打出了正解。
此时是 43min。还有一个小时。
看 F 题。发现太典了。题目中字字句句都在提示二分,而二分的 check 又是一个入门贪心。想了一两分钟就开始写了。
越写越觉得 check 太过麻烦,但是还是硬着头皮写下来了份 140+ 的代码。没有调试,发现比答案少一。加上一后直接交了。结果 AC15 WA35。简单修改变成了 AC26 WA24。
然后发现加一绝对是错误的。去掉后开始疯狂调试 + 补充代码。赛时我的代码中写了若干个二分,没有把二分封装成函数,结果赛后发现每个二分都写错了。除此之外小错误和恶心边界比比皆是,写着写着就有些崩溃了。
于是硬生生地冲着 CP Editor 写了一个小时。比赛结束。
这份代码已经丑陋到 170+ 了。想了想还是重构代码吧。赛后一小时终于过了。
这里列几个犯的错误:
int getp(int l, int r, int k, int w) { // [l, r] 中第一个 p 使得 [l, p] 中 w 出现 k 次
int pos = -1, L = l; // 要把最开始的 l 记录下来
while (l <= r) {
int mid = l + r >> 1, S = calc(L/*这里不能用 l,需要用最开始的 L*/ , mid, w);
// if (S == k) return mid; 是错误的。
if (S >= k) pos = mid, r = mid - 1;
else l = mid + 1;
}
return pos;
}
bool chk(ll k) {
pair<ll, int> cur = {1, 0};
for (int i = 1; i <= lb; ++ i ) {
cur = nxt(cur.first, cur.second, b[i] - 'a', k);
if (cur.first > n) return false;// 如果不写这行,在最后写 return cur.first <= n,那么 cur.first 会超出 long long 的范围
}
return true;
}
标签:二分,AtCoder,return,Beginner,int,代码,mid,346,ll
From: https://www.cnblogs.com/2huk/p/18091925