牛客小白月赛39C - 奋发(数学规律 + 贪心 + 模拟 + *1600)

牛客小白月赛39C - 奋发(源地址自⇔牛客


tag

⇔数学规律、⇔贪心、⇔模拟、⇔*1600左右

题意

给定两个长度为 \(N\) 的非降序列 \(a,b\) 以及两个初始为 \(0\) 的变量 \(A,B\) 。现在按如下规定进行操作:

  • \(A=a_n\) 并且 \(B=b_n\) ,直接结束所有操作;
  • 如果存在 \(a_k=A\) 并且 \(b_k>B\)\(++B\)
  • 如果存在 \(b_k=B\) 并且 \(a_k>A\)\(++A\)
  • 如果上述的条件均不满足,则任选一个 \(+1\)

在每一次操作之后,如果存在 \(A=B\) ,则令 \(ans + 1\) 。直到操作结束,输出 \(ans\) 的最大值。

一组样例,满足 \(1≤N≤3∗10 ^6 ;1 \leq a_i,b_i\le 2*10^9\)

思路

赛时小结

我试图从形象的角度思考寻找规律,所以我出了很多个测试集并且尝试总结,然而直到比赛结束都没能解出。赛后复盘时我发现自己刚开始的思路就已经非常接近正确答案了,但是问题在于没有对于一种情况进行特判。下方的思路我将从抽象+形象结合的角度进行解剖,也算是提升一下自己的抽象思考能力吧。

正解

很显然,初始的情况 \(A=B=0\) ,直到其满足操作 \(2\)\(3\) 之前,都需要执行操作 \(4\) 。这一阶段,我们依次让 \(A+1,B+1\) 这样循环,会使得 \(ans=ans + min\{a_i,b_i\}-0\) 。在这之后会重复步骤 \(2\)\(3\) ,而这两步操作不会对 \(ans\) 造成影响。

例如:"0,0" -> "2, 3"。

过程为:"0,0" -> "2,2" -> "2,3"。从过程 \(_1.\)\(_2.\) 执行的是操作 \(4\) (答案 \(+2\) ),从过程 \(_2.\)\(_3.\) 执行的是操作 \(2\) (答案不变化)。

再考虑接下来的操作,我们需要再次执行操作 \(4\) ,使得 \(A=B=max\{a_i,b_i\}\) ,这一步操作过程中不会对 \(ans\) 造成影响,而当达成 \(A=B\) 时,会使得 \(ans = ans + 1\)但是注意,如果在上一步操作中 \(a_{i-1}=b_{i-1}\) ,那么这一步将被略去!

例如:"2,3" -> "5,6"。

过程为:"2,3" -> "3,3" 。执行操作 \(4\) (答案 \(+1\) ),然后重复。

例如:"3,3" -> "5,6"。

过程为:直接重复。

重复,直到完成操作。

AC代码

点击查看代码
void Solve() {
	int ans = 0, xx = 0, yy = 0;
	int n; cin >> n;
	for (int i = 1; i <= n; ++ i) {
		int x, y; cin >> x >> y;
		int w = min(x, y) - max(xx, yy) + (xx != yy);
		ans += max(w, 0);
		xx = x, yy = y;
	}
	cout << ans << endl;
}

错误次数

(赛时1次)忘记特判 \(a_{i-1}=b_{i-1}\) 的情况。

(赛时无数次)尝试穷举所有情况失败。


文 / WIDA
2022.03.20 成文
首发于WIDA个人博客,仅供学习讨论


posted @ 2022-03-20 15:32  hh2048  阅读(33)  评论(0编辑  收藏  举报