Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

[NOIP集训]10月20日

今天的文件夹:10月20日.zip

今天是搜索题专练。

T1:这题用搜索找规律可以,AC就别想了。搜索起来,每次枚举两种操作(push和pop),判断是否合法,递归2n次后比较出栈序列并统计总数。当然,对于极限数据这是不能通过的(一共要递归2n层,总的时间复杂度为O(22n)),因此要用数学方法。

经过数学上的推导(详情百度,这里给大家一个链接百度百科),结果应该是第n个Catalan数,即

h(n)=n1i=1h(i)h(ni)=h(n1)4n2n+1=Cn2nn+1

其中h(0)=h(1)=1

计算输出即可,注意数据不要爆了int64。

T2~T9晚上再填。。。

T10:对于不能的情况,方法很简单。我们对所有的临近湖泊的点做一次BFS,看能到达临近沙漠的哪些点,最后统计输出即可。而对于能实现的情况,我们也可以用这种方法,统计出每个临近湖泊的点如果修建蓄水池的话,可以到达的所有点。

现在,我们有了这些数据,要求出覆盖所有临近沙漠的点时,最少要修建的蓄水池个数。这看起来很像一个集合覆盖问题,然而这个问题貌似是NP难的,不可能实现这样的规模。这告诉我们,这道题一定存在一些特殊性,只是还没有被利用。

考虑样例2,我们发现,对每个最上面的点(记为a[1,i]),可以到达最后一行的点(记为a[n,j])的集合,总能构成一条连续线段。例如,a[1,1]可以到达a[n,1],a[n,2]a[1,3]可以到达a[n,2],a[n,3],a[n,4]等等。这条规律是否普遍成立,还要证明:

定理:在能满足要求,即每一个点a[n,j](1im)都可到达的情况下,对任意点a[1,i](1im),它可以到达的最后一行的点总是连续的一段。

证明:采用反证法,假设存在一个点(或一个区间),它左右两侧均可由同一点到达,而这个点不能。

因为所有点都能被到达,所以必有一个最上方的点可以到达这个点,这两点间的路径(记为p)肯定与a[1,i]到左右两侧的两个点的两条路径中的至少一条相交(可以分情况证明),那么我们在交点处,令a[1,i]出发的路径沿着p行进,可以到达a[n,j]而不违反任何规则。这就推出了此点可以由a[1,i]到达,发生矛盾。

综上,定理得证。因此,这些集合可以看做m条线段,要让它们覆盖另一条线段。这不就是经典的线段覆盖模型吗?我们令s[i],t[i]分别表示第i条线段的起点、终点,ans[i]表示线段1..i至少需要多少条线段来覆盖,那么

ans[i]=min

posted @   常可  阅读(193)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示