Loading

AGC 061 C First Come First Serve 题解

链接

这题思路比较奇妙,本篇完善了一些结论的证明。

这道题是一个计数问题,怎样才能做到不重不漏的计数便是关键。如果枚举登记的顺序,不太好判断是否存在一种情况满足条件。

我们定义一个长度为 $n$ 的只包含 $A$ 和 $B$ 的序列表示一种选取方式。对于一种合法的登记方式,可能有多种选择不同的序列。我们为了不重复,只统计**字典序最小**的序列。

现在问题就变成了如何判断序列是否可以通过改变一些字符,使得字典序变小,而且使得最终的登记序列不变。

需要使得字典序变小的条件就是依次考虑每一个选择 $B$ 的人 $i$,如果 $[l_i,r_i]$ 的时间段没有其他人登记的话,就可以把这个位置变成 $A$,所以这种序列不被统计。

我们现在需要证明的是如果对于每一个选择 $B$ 的人 $i$,$[l_i,r_i]$ 的时间段都存在一个其他的人登记,那么这个序列就是字典序最小的。即不存在一个字典序小于它的序列,使得最后的登记序列相同。

如果可以使得字典序变小,那么就会把一个最小位置 $i$ 的 $B$ 变成 $A$,并且这个区间里有一个人 $j$ 在某个时间登记。因为区间不存在包含关系。如果 $j$ 选择的是左端点,那么在这之前,$j$ 在 $i$ 前登记,变成了 $i$ 在 $j$ 前登记,不满足前后登记序列相同;如果 $j$ 选择的是右端点,那么 $j$ 位置就选择的是 $B$ ,并且为了保证 $i$ $j$ 相对顺序不变,$j$ 位置就要变成 $A$。但由于 $i$ 的最小的,所以矛盾。

综上,我们只需要统计上述的合法序列的数量,就是答案。

考虑容斥,设 $f_i$ 表示钦定有 $i$ 个位置选的 $B$ ,并且 $[l,r]$ 没有其他的点的方案数,答案就是 $\sum_{i=0}^nf_i(-1)^i$ 。我们发现这 $i$ 个区间一定是不相交的。而其他的区间由于 $l$ $r$ 都递增,最多和这之中的一个区间相交。对于其他没有被钦定的区间,如果和一个区间相交,那么只有一种选择;否则有两种选择。定义 $f_i$ 为考虑前 $i$ 个区间对答案的贡献,转移是简单的,代码也很简洁。

代码:

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int mod=998244353,N=5e5+5;
int n,a[N],b[N],l,r,f[N];
int main() 
{
	scanf("%d",&n);f[0]=1;
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
	for(int i=1;i<=n;i++)
	{
		f[i]=((ll)f[i]+f[i-1]+f[i-1])%mod;
		while(r+1<=n&&a[r+1]<b[i]) r++;
		while(l<=n&&b[l]<a[i]) l++;
		f[r]=(f[r]-f[l-1]+mod)%mod;
	}
	printf("%d",f[n]);
	return 0;
}
posted @ 2023-09-20 14:52  Bobby7000  阅读(59)  评论(0)    收藏  举报