NOIP 2015 简要题解

最终还是打了个漂亮的酱油

[Day 1]

T1 神奇的幻方

送分模拟题,但是遇到了一个非常流弊的学弟:

 

 

/*************************************以上纯属娱乐 割********************************************/

T2 信息传递

大意:在一个只有n条有向边的图中,每个结点出度为1,求一个包含节点数最少的环。

分析:因为只有n条边并且每个点都有且仅有一条边连出去,所以只可能存在简单环,不会出现那种8字形的环套环。

证明:每个点有两种情况:1.不在任何一个环中 这样的点可以直接忽略掉,看成是有n-1个点,n-1条边来证明就行了。2.在某个环中。那么如果我们现在有了一个圈圈形状的环,大小为k,那么每一个点都应该入度出度都为1,这样的环只存在一个回路,也就是一个简单环,如果存在多个回路,那么应该存在某个点的入度>1,但是又要保证别的点出度至少为1,所以出度之和应该是>k的,但入度之和=k,无法满足,所以不存在某个环存在两条或以上数量的回路。证毕。

满足了这样的性质,tarjan或者O(n)扫描都是可以解决本题的。

T3 斗地主

与一些HN、ZJ的选手在网上讨论,觉得这道题目作为第三题,没有体现出应有的价值,只是让很多人在这上面花费了大量时间而已,并且首先题目描述有不清晰之处,而且数据纯随机也让人很不是滋味,毕竟也许有的人用搜索剪枝碰巧能拿高分甚至AC,而那些写的很好的标准算法却被卡掉,OI毕竟不是运气的较量,而是实力的争夺。

因为之前模拟赛的时候写过一次状压DP爆空间,然后这道题空间1G太过耀眼,再加上NP问题复杂的状态以及相对略小的数据范围,在考场上就朝着状压DP的方向思考,首先对于每一副手牌,我们预处理出每一种可能的出牌方式,然后丢进一个数组里,在DP的时候,记录一个cnt表示当前是第几次出牌,用bool[i](i是二进制数)表示出cnt次牌时,状态i是否能实现,然后只要某一次满足2^m-1也就是所有牌全出掉的情况可以实现时就退出,此时的cnt就是最少出牌次数。

具体时间复杂度根据每副牌而有很大差异,但是应该过60%的数据是没有问题的。

赛后补:拿到程序以后再写了写,状压DP确实是能过60%的点,但是想AC的话还是要用到DFS+状压DP或者直接A*

 

[Day 2]

T1 跳石头

看到最大值最小或者最小值最大之类的问题,很容易想到是二分答案,
具体说明:假设我们已经知道答案是k,也就是满足最小的距离最大为k,那么最终搬走石头以后任意两个石头之间的距离都是大于等于k的,那么我们只要检验是否能搬走m块石头使得满足k就可以了。
首先,题目告诉我们,起点石头也就是0是固定的,然后如果我们搬走一个石头i的话,如果左边的石头已经满足答案k,那么移除i对答案是没有影响的,因为到左边石头的距离只会变大,不可能小于k。
对于当前的石头i,下一块石头为j,pre[i]为i上一块石头,sub[j]为j下一块石头


有两种可能:
1.i到j的距离小于等于k,也就是不满足答案,那么我们要做的是,移除j。
因为i到pre[i]是>=k的,那么j到pre[i]一定也>=k,但是i都不一定满足i到sub[j]的距离>=k,更不谈离sub[j]更近的j了,所以为了之后的石头考虑,我们需要移除j。
2.i到j的距离大于k,也就是i,j之间已经符合条件了,那么就可以什么都不动了。
因为i到j的距离已经大于k了,所以对于j之后每一块石头,都是满足条件的,所以i对检验答案并没有什么影响了,那j如何考虑呢?j之后就会成了下一个i,再如上文分两种情况处理了。
所以具体就是二分答案k,然后O(n)检验,总复杂度O(nlogL)。

PS:有一种特殊情况需要考虑,也就是n可以等于0,这时候答案直接就是L,但是处理方法很简单,二分的时候要将上界设为L,这样就不会有什么影响了。

 

T2 子串

大意:求将B串选出k段,顺次拼起来能构成A串的方案数。

本题的阶段非常鲜明,f[i][j][t]表示A,B分别匹配到i,j位时,已经用到了B的第t个子串的方案数,另外match[i][j]表示A,B分别匹配到i,j位时,最多可以向前匹配多少位,如A=cabab,B=cab,那么match[5][3]=2,match可以暴力预处理出来。

考虑第i位不匹配和最多向前匹配match[i][j]位的情况,由此得出转移方程:


但是很明显这样的复杂度在最坏情况下是O(n*m^2*k),所以我们要考虑优化。

首先是空间上:n*m*k可以达到4kw,明显不够用,然后我们发现,选到第t个子串的方案数只和选到t-1个子串的方案数有关,所以我们考虑以时间换空间,用滚动数组,f[0]和f[1]两个二维数组交替使用,解决空间问题。

然后是时间上:观察这个转移方程,实际上是一个求和,那么具体是什么呢?我们如果把f[i][j]看成一个二维矩阵,那么实际上就是求的以i-1,j-1(因为每个子串不能为空所以至少要选一个)为右下角,i-match[i][j],j-match[i][j]为左上角的的正方形的主对角线上的元素之和,所以对于这种求和,我们可以考虑用类似前缀和的方法O(1)转移,另开数组g[i][j]表示以i,j为右下角的整条斜线上元素之和,那么转移方程就更新为:

这样就降掉了一个O(m)的时间,但是因为使用滚动数组而且常数有点大,所以在实际枚举的时候再注意一些小优化剔除一些不必要的状态。

T3 运输计划

在考场上并没有做出来,敲了个50的朴素,后来请教了一下wzy和zk,太厉害了。

大体框架就是二分答案然后用LCA来检验。

但是有几个注意点:

1.二分的时候wzy是直接二分路径总长度,zk是二分的选取的作为虫洞的边的长度,这样就差距了约一个log级别的复杂度,但对实际效果是一样的,这点值得吸取教训。

2.求LCA的时候如果用普通的倍增会挂掉,要用Tarjan离线求LCA。

3.还未解决的内容:我们在做路径处理的时候可以用一些特殊的技巧,给每一个点一个权值,在LCA的时候顺带处理一下,然后就可以得到每一条边被多少条路径覆盖了,方便之后检验答案。

 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值