﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Mato is No.1-随笔分类-COCI</title><link>http://www.cppblog.com/MatoNo1/category/18854.html</link><description>Mato是一只超级大沙茶……比赛结果从后往前排列，Mato总是No.1……</description><language>zh-cn</language><lastBuildDate>Mon, 07 May 2012 06:46:43 GMT</lastBuildDate><pubDate>Mon, 07 May 2012 06:46:43 GMT</pubDate><ttl>60</ttl><item><title>COCI 2011～2012 #5 后两题题解</title><link>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Wed, 18 Apr 2012 12:26:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/171899.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/171899.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/171899.html</trackback:ping><description><![CDATA[<a title="相关链接" href="http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html">相关链接</a><br />今天在回顾以前的题目的时候，秃然发现COCI 2011～2012 #5的后两题并非神犇题（至少一般人可以捉的）&#8230;&#8230;是我当时想傻掉了囧&#8230;&#8230;<br /><br />blokovi：<br />首先很容易发现最优方案必然是从顶到底，先尽量往右边放，放到某一个转折点处再尽量往左边放&#8230;&#8230;<br />然后就是枚举这个转折点，乱算一下就行了，暴力O(N<sup>2</sup>)的可以过7个点（本沙茶现场赛时就是用这个的）&#8230;&#8230;<br />优化：可以从上到下依次枚举转折点，设目前的转折点为i，则在下一次枚举时（(i+1)为转折点），把(i+1)往右平移2单位，然后根据那个重心计算公式可以得出，第(i+2)个及以后的必然是整体向右平移(2*m2)/(m1+m2)，其中m1为前i个的质量和，m2为第(i+1)个的质量&#8230;&#8230;在此基础上维护转折点前重心位置、转折点的重心的横坐标（相对于最上面的那个）以及最下面的那个的重心的横坐标（相对于最上面的那个）就行了（注意转折点是第一个或最后一个的特殊情况要单独处理），时间复杂度O(N)。<br /><br />poplocavanje：<br />其实这题只要用AC自动机随便乱搞一下就行了&#8230;&#8230;Trie上的每个结点维护一个KK，表示该结点所代表的字符串的后缀的最大匹配长度（当然前提条件是该结点是危险的），则：（1）若该结点本来就代表一个待匹配的子串，则KK值为子串长度；（2）若该结点是通过失败指针上溯到一个危险结点的，则该结点的KK就是上溯到的那个危险结点的KK。然后做一次匹配，记下所有的匹配区间，再求出未被区间覆盖的总长度（排序+扫描即可，不需任何数据结构）就行了。<br /><br />注意几个易疵的地方：<br />（1）Trie的大小要开到4M才能过（不过再大就要MLE了囧&#8230;&#8230;）；<br />（2）在建自动机计算KK的时候，如果一个结点本来就是危险的（即上述第1种结点），此过程中又发现它是上述第2种结点，则<strong><span style="color: #ff0000;">不</span><span style="color: red;">能重新计算KK</span></strong>；<br />（3）最后求未被区间覆盖总长度的方法：先记下所有的区间，按照先左端点递增序后右端点递增序排序，当中去掉被别的区间覆盖的区间，然后先看一下排序后的第一个区间和最后一个区间，得出第一个区间之前与最后一个区间之后的未被覆盖的部分，中间的扫描求解时，如果某区间的左端点大于(前一区间的右端点+1)，则计入中间的空当&#8230;&#8230;不过还有一种方法就是不去掉被别的覆盖的区间，而是在扫描过程中维护右端点最大值maxr，然后把上面方法中的所有右端点改为maxr即可。<br /><br />代码：<br /><a title="blokovi" href="http://ideone.com/APoKA">blokovi</a> <a title="poplocavanje" href="http://ideone.com/aWQ8O">poplocavanje</a><img src ="http://www.cppblog.com/MatoNo1/aggbug/171899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-04-18 20:26 <a href="http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COCI 2011~2012 #6</title><link>http://www.cppblog.com/MatoNo1/archive/2012/04/15/171416.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sat, 14 Apr 2012 17:19:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/04/15/171416.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/171416.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/04/15/171416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/171416.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/171416.html</trackback:ping><description><![CDATA[【很难过吧&#8230;&#8230;考得完爆了&#8230;&#8230;<br />&#8230;&#8230;其实也没什么可以说的&#8230;&#8230;都是蒟蒻的借口罢了&#8230;&#8230;<br />&#8230;&#8230;自己果然还只是半吊子水平呢&#8230;&#8230;】<div><p><br /></p><p>(结果：Rank36&#8230;&#8230;我是&#8220;真&#8221;沙茶！！！！！！！！！！！！！！！Orz Mike_Qiao神犇虐人）</p><p><br /></p><p>题解以后再发。</p><p><br /></p></div><img src ="http://www.cppblog.com/MatoNo1/aggbug/171416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-04-15 01:19 <a href="http://www.cppblog.com/MatoNo1/archive/2012/04/15/171416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COCI 2011 OPEN</title><link>http://www.cppblog.com/MatoNo1/archive/2012/04/01/169537.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 01 Apr 2012 12:42:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/04/01/169537.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/169537.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/04/01/169537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/169537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/169537.html</trackback:ping><description><![CDATA[<div>历经千辛万苦总算搞定了COCI 2011 OPEN的所有题&#8230;&#8230;真WS啊囧&#8230;&#8230;<br />（不过除了sort的满分算法稍微看了一下题解之外，其它的题目都是自己想出来的&#8230;&#8230;这说明本沙茶想算法的能力并不差&#8230;&#8230;只是所用的时间有点&#8230;&#8230;）<br /><br />sort：很容易想到该置换的循环分解，然后对每个长度大于1的循环进行一次操作就成了，总操作次数是长度大于1的循环个数。但是，这并不是最优解（在官方数据中，这个算法能过4个点，加上剩下6个点的一半分总共是70分，所以现场结果中多数人都是70分&#8230;&#8230;）。最优解是先通过一次操作把各个长度大于1的循环搅乱，使得整个置换只有一个循环，然后再来一次操作就行了，也就是任何置换都最多只要两次操作就行&#8230;&#8230;至于搅乱的方法，只要在原来的各个循环（当然是长度大于1的）中各抽出一个元素，再对这些抽出的元素执行一次题目中的操作即可（证明是很容易的）。不过要注意只需0次或1次操作的情况：当原置换长度大于1的循环总数为0或1时；<br />至于具体的操作构造方法随便乱搞一下就行了囧&#8230;&#8230;<br /><br />telka：应该算是最水的一题&#8230;&#8230;树状数组的裸模型&#8220;改段求段&#8221;（具体见<a title="这里" href="http://www.cppblog.com/MatoNo1/archive/2011/03/19/142226.html">这里</a>），唯一值得注意的就是在改段求段模型中的一个注意点：当l=1的时候，不能执行opr(l-1, c)，因为凡是下标递增的数组都不能以0作为初始下标；<br /><br />rijeka：这题比较坑人啊囧&#8230;&#8230;如果任意时刻最多只能载一个人，可以把每个人的要求（也就是每条有向线段）都拆成若干个元线段，然后统计正反元线段的个数，乱搞一下就成了&#8230;&#8230;不过这题目里面是可以载任意多的人&#8230;&#8230;那么最优策略是：先把所有反方向线段覆盖的总区间求出来，比如有4-&gt;2、6-&gt;3、9-&gt;8三条反方向线段，则覆盖的区间就是[2, 6]和[8, 9]，然后在送人的时候，每送到一个区间的右端就回头去把这个区间内的要走反方向的人全送到，然后再回头往正方向开（比如上例中先从0到6，回到2，再从2到9，回到8，再回头往前一直开到终点），这样开到终点时，所有的人就都送到了，因此，总时间就是(M+反方向线段覆盖的总长度)，用线段树来搞。此外，由于M太大，需要离散化。<br /><br />后面两题就是猥琐题了。<br /><br />kamion：很明显是个递推&#8230;&#8230;但是按照常规方法根本无法划分状态。不过，要发现本题和括号序列类的动态规划神似，因此就可以用括号序列的来搞。关键是，对于那些第3种边（既不含左括号也不含右括号的）比较难搞，另外本题还允许到终点的时候有左括号（就是大写字母）剩余，这就明显加大了难度。<br />状态设计应是这样的：F[i][j][k][s0][s1]，表示从i到j走正好k步，且满足单多段限制（s0）和多余左括号限制（s1）的合法路径总数，s0、s1为bool，s0表示是单段还是多段的规则括号序列，0：单段，1：单段或多段；s1表示是否可以有多余左括号，0：不能有；1：可以有（当然也可以木有，也就是s0和s1都是0包含在1之中的）。<br />递推式：<br />F[i][j][k][0][0]=<font class="UNICODE">&#931;</font>F[t1][t2][k-2][1][0]（其中&lt;i, t1&gt;边有一左括号，&lt;t2, j&gt;边有一右括号，且两括号匹配）；<br />F[i][j][k][1][0]=&#931;F[t1][t2][k-2][1][0] + &#931;(F[i][t][k'][0][0] * F[t][j][k-k'][0][1]) （注意0&lt;k'&lt;k，其它的类似）；<br />
<div>F[i][j][k][0][1]=&#931;F[t1][t2][k-2][1][0] +&nbsp;<font class="UNICODE">&#931;F[i][t][k-1][0][1]（其中&lt;i, t&gt;边有一左括号，其它的类似）；<br />F[i][j][k][1][1]=</font><font class="UNICODE">&#931;F[t1][t2][k-2][1][0] + </font><font class="UNICODE">&#931;(F[i][t][k'][0][0] * F[t][j][k-k'][1][1]) + </font><font class="UNICODE">&#931;F[i][t][k-1][1][1]（与上面的限制类似）；<br />边界：F[i][i][0][0..1][0..1] = 1，当&lt;i, j&gt;边为第3种边（不含括号）时，F[i][j][1][0..1][0..1] = 1，其余的均为0。<br />这几个式子还是比较好理解的，要注意的是在计算F[i][j][k][1][1]时，是F[i][t][k'][0][0]而不是F[i][t][k'][0][1]，这是为了防止重复计数（否则，对于序列AB，到底是A是附加上的，B是原来就有的，还是都是附加上的？显然被计2次了）；<br />时间复杂度O(N<sup>3</sup>K<sup>2</sup>），官方题解里面说这个就能AC了，可是本沙茶实测的结果却有5个TLE，最慢的点达14+s，可见其常数之大，本沙茶暂未想出神马好的优化方法，神犇们可以提供一些啊囧（最好能降一维）；<br /><br />lovci：（这题本沙茶调了3个晚上啊啊&#8230;&#8230;）<br />本沙茶所见过的最猥琐的暴搜题目了。由于当M&gt;0时，初始位置就会被计入（本题的真正意思是每个格子只被计入一次，而不是每次移动中初始位置控制不到的地方就计入一次），因此不用考虑初始位置。仔细分析题目发现，可以对矩阵进行黑白染色，这样两个初始位置一个只能控制黑格，一个只能控制白格，这样就把两个分开了。然后，把所有的黑格和白格给旋转45度，变成一个十字型，剩下的任务就是枚举哪些列被占用，然后再选出哪些行能被占用就行了。<br />问题是，有的列不能随便选，有的行也不能随便选，这下就囧了，需要很多东东来控制，当然，本题需要注意的点太多了，实在列举不完，见代码吧囧。<br /><br />代码：<br /></font><a title="sort" href="http://codepad.org/6dcEICLj">sort</a> <a title="telka" href="http://codepad.org/i50ZOWLh">telka</a> <a title="rijeka" href="http://codepad.org/lwdVNWrc">rijeka</a>&nbsp;<a title="kamion" href="http://codepad.org/spZvaCYl">kamion</a> <a title="lovci" href="http://codepad.org/OUEwCvWk">lovci</a></div></div><img src ="http://www.cppblog.com/MatoNo1/aggbug/169537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-04-01 20:42 <a href="http://www.cppblog.com/MatoNo1/archive/2012/04/01/169537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COCI 2011~2012 #5</title><link>http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sat, 17 Mar 2012 17:14:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/168229.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/168229.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/168229.html</trackback:ping><description><![CDATA[刚捉完&#8230;&#8230;这次的题目感觉和前几次难度差不多啊囧&#8230;&#8230;还木有被虐得太惨（当然，我是沙茶，被虐是必然的）<br /><br /><div>krizaljka: 超级大水题；<br /><div>eko: 如果真是用裸的二分法（不T）的话，就是超级大水题；<br />dna: 水题，从后往前扫描，如果遇到B，就进行一次变换（如果该B位的前一位也是B，则进行整体取反，否则，即该B位的前一位是A或者该B位在最前面，则进行单位取反），可以用一个bool记录前面目前是否被取反了；<br />razbibriga: 水题，直接枚举四个角的字母就行了，然后在计数的时候，要排除掉同一个字符串被用多次的情况，因此对于2行2列的4个字符串中有首尾字母都相同的要特判一下，具体的特殊情况有点多，这里不列举了囧；<br />blokovi: 神犇题！本沙茶只会暴力；<br /><div>poplocavanje: 神犇题！本沙茶只会暴力；<br /><br />结果&#8230;&#8230;前4道水题AC了，blokovi竟然搞对了7个点（这&#8230;&#8230;难道贪心是正解？），但是poplocavanje得分比预想的要低了囧（不知是哪里疵了）&#8230;&#8230;总分478，rank17（全国除了ZL外的神犇都木有参加，说明我在沙茶中都是rank16&#8230;&#8230;哭死&#8230;&#8230;）</div></div></div><img src ="http://www.cppblog.com/MatoNo1/aggbug/168229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-03-18 01:14 <a href="http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COCI 2011~2012 #1~#4 题解</title><link>http://www.cppblog.com/MatoNo1/archive/2012/03/16/168113.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Fri, 16 Mar 2012 12:56:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/03/16/168113.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/168113.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/03/16/168113.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/168113.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/168113.html</trackback:ping><description><![CDATA[【背景（神犇不要鄙视）】<br />前段时间，本沙茶在捉神马题都被完虐的情况下，发现了COCI&#8230;&#8230;一看，发现里面有相当数量的水题，于是就去捉了&#8230;&#8230;结果，本想体验虐题的感觉，可还是被里面的一些神犇题虐了&#8230;&#8230;我太沙茶了，没脸见人了囧&#8230;&#8230;<br /><br /><a title="COCI官网" href="http://www.hsin.hr/coci/">COCI官网</a><br /><br />2011~2012 #1：<br />jabuke: 超级大水题；<br />matrix：超级大水题，不过本沙茶一开始看疵题了&#8230;&#8230;<br />x3: 水题，直接对每一位单独考虑即可；<br />ples: 水题，裸DP；<br />sort: 这个题看上去很不好搞囧&#8230;&#8230;但注意题目里面的这个条件：一开始各极大递减子序列的长度均为偶数（也就是均&gt;1），这样，第一次模拟一遍以后，剩下的极大递减子序列就只有长度为2的了，这时每个数要归位需要与其后面所有比它小的数都交换一次，所以结果就是第一次模拟的rev执行次数加上第一次模拟之后的逆序对总数；<br />skakac: 神犇题，因为涉及比较难的知识点，本沙茶暂时不会搞囧&#8230;&#8230;<br /><br />2011~2012 #2：<br /><div>najboljih5: 超级大水题；<br />okret: 超级大水题，注意特殊情况即可；<br />zadaca: 水题，直接因数分解一遍，再查找相同的因数（用哈希），求较小值即可，对于10^9的判定应该很容易的，注意特殊情况；<br />kompici: 中等难度，需要用到容斥原理，对于开始的10^6个数，由于本质不同的只有1024个，所以可以压缩成1024种情况，这样总的复杂度就是1024*1024了；<br />funkcija: 神犇题！！巨神无比的递推！！这里面涉及到的思想需要慢慢总结；<br />raspored: 中等难度，模型转化后可以发现T是无用的，只需要按照时间递增的顺序执行任务（贪心的经典模型），然后用线段树维护这个递增序的和就行了；<br /><br />2011~2012 #3：<br />digitalna: 超级大水题；<br />dhondt: 超级大水题，关键在于题意的理解（是把每个派别的选票总数依次除以1到14，得14个结果，然后汇总起来取前14大的结果对应的派别，不是按比例）；<br />pogodak: 水题，暴力模拟即可；<br />robot: 水题，注意二分查找的边界（比如要找大于等于给定值的最小值，需要特判所有的值都小于给定值的情况）；<br />place: 超级大水题，裸得不能再裸的模型了；<br />traka: 本张试卷的唯一一道不水的题（是个神犇题），首先很容易模型转化为求F[i]S[i-1]-F[i+1]S[i]的最大值，由于F是个定值且为正，可以除以F[i]，变成S[i-1]-(F[i+1]/F[i])*S[i]，可以看成直线y=S[i-1]-S[i]*x，当x=F[i+1]/F[i]时的纵坐标，这样把所有的直线搞出来，维护下凸壳即可（当然本沙茶至今未做过这样数形结合的题目囧&#8230;&#8230;以后可以搞一个专题）；<br /><br />2011~2012 #4：<br />kino: 超级大水题，贪心就能搞定；<br />zima: 水题，线段树操作，注意细节（本沙茶一开始把下放标记dm()中的mr_opr(LCH(No))，mr_opr写成dm了&#8230;&#8230;成递归调用了&#8230;&#8230;为此查了2h+）；<br />keks：超级大水题，贪心经典模型，不要管前导0的问题；<br />ograda：这个是神犇题了（因为本沙茶总是搞不定啊囧&#8230;&#8230;），首先由于相邻元素的大小关系以定，绝对值号可以去掉的（本沙茶竟然木有想到这个），然后根据贪心思想，应当尽量把大的和小的交替放置，而且这样必然能得到可行解（详细证明见官方题解）；<br />broj：中等难度，P&gt;=5000时可以直接筛，P&lt;5000时用容斥原理（表面上需要计算2<sup>N</sup>次，N是小于P的质数总数，其实很多交集都是空集，可以忽略掉，最后剩下的非空集合很少的囧&#8230;&#8230;这也是容斥原理之所以广泛应用的原因啊囧&#8230;&#8230;）<br /><div>kriptogram: 中等难度，首先各个单词可以映射到Trie里面，变成编号，然后就是类似KMP的搞法了（类似于WC2012 Day1上午讲的那道CEOI题目）&#8230;&#8230;本沙茶用官方数据本机测试AC，但交上去RE了两个点&#8230;&#8230;说是Trie爆了&#8230;&#8230;（本机测试时跟踪了一下，发现木有爆）主要是这题空间卡得太死（64M），而Trie的空间由于要乘上一个104，所以不能开太大（或许这里可以优化，但本沙茶还不会啊囧&#8230;&#8230;）<br /><br /></div></div><img src ="http://www.cppblog.com/MatoNo1/aggbug/168113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-03-16 20:56 <a href="http://www.cppblog.com/MatoNo1/archive/2012/03/16/168113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>