2015 "BestCoder Cup" Champion
这场比赛我没有参加,不过就算参加了也估计是被完虐。于是看着题解把大部分题目都搞了一遍。
T1:Movie(hdu 5214)
题目大意:
给出N个区间,问能否选出3个互不相交的区间。 N<=106.
题解:
贪心的思想,先找出右端点最小的和左端点最大的,看中间能不能夹一个区间就好。
T2:Cycle(hdu 5215)
题目大意:
给出一个无重边无自环的无向图,求有无简单的奇环和偶环.|V|<=105,|E|<=3*105.
题解:
1.如果只要求奇环的话 判一下二分图就可以了。偶环的情况比较恶心.我自己yy了一下,发现偶环要么是极小的偶环(不能拆成多个环),要么是偶数个奇环拼起来。 对于2个有公共点的环拼起来(去掉公共边),易得奇环+奇环=偶环,偶环+奇环=奇环。
所以我就对每个点求出有多少个极小的偶环经过它,以及有多少个极小的奇环经过它.如果偶环数>=1或者奇环数>=2说明存在一个偶环。
2.那么如何求出有多少个极小的偶环经过某个点呢? 只要一次Dfs就好。对于一个点x,只要加上它所有儿子的答案,如何减去到它的儿子就结束的环。具体见代码。
1 void Dfs(int x,int c)
2 {
3 int y; vis[x]=instack[x]=true,color[x]=c;
4 for (int i=head[x];i!=-1;i=nxt[i])
5 {
6 y=to[i]; if (y==father[x]) continue;
7 if (!vis[y])
8 {
9 father[y]=x;
10 Dfs(y,c^1);
11 Odd[x]+=Odd[y];
12 Even[x]+=Even[y];
13 }
14 else
15 {
16 if (instack[y])
17 {
18 if (color[x]==color[y]) Odd[x]++;
19 else Even[x]++;
20 }
21 else
22 {
23 if (color[x]==color[y]) Odd[father[x]]--;
24 else Even[father[x]]--;
25 }
26 }
27 }
28 if (Even[x] || Odd[x]>=2) flag2=true;
29 if (Odd[x]) flag1=true;
30 instack[x]=false;
31 }
T3: segment(hdu 5216)
题目大意:
给出一个A数组,和一个B数组.如何要给AB中的元素随意配对,使得A[i]<=B[i]. 有N个白点,把[A[i],B[i]]的点染黑。
求连续的白点的最长长度的期望。
题解:
显然根据贪心可以找到一种配对方案,即把A数组和B数组都从小到大排序。如果这样不能配对,那么其他方式也不能。
如果其他方式能配对,必定是交换了数组中的元素,然后YY一下可以知道交换2个元素是不会影响染色的总区域的。
所以根本不要考虑概率,直接排序后求就好了。
T4:brackets(hdu 5217)
给出N个括号"("或者")",然后要支持修改一个位置的括号和询问区间[L,R]的括号合并之后第K个括号在原数组的位置。
N,Q<=200000.
题解:
这题是我做的最蛋疼的一题了,合并的时候分类讨论什么的恶心死了。任意一个区间合并之后必然会是"))))((("这样的。首先可以一次询问求出在线段树上每个区间合并之后的结果,判断无解的情况,然后再搞一次来求出位置. 求位置比较恶心,首先递归的时候考虑左右区间,如果左边区间的")"大于等于K,答案必定在左边。在看看把右边区间的")"和左边区间的"("合起来,如果右边区间的")"少一些,那么相当于把左边区间的一些"("消掉了。 然后看左边剩余的如果大于等于K,还是递归左边。 否则递归右边(还要搞一搞看看等价于求右边区间的第几个括号)。 分类讨论神志不清了。
T5: Game(hdu 5218)
题目大意:
N个人的约瑟夫问题,每次隔x个人删掉,x必须是属于某个已知的集合S。 求最后可能剩下来的人。 N<=100.
题解:
一开始以为是神题,不会做。。然后就很没志气的看题解了。其实就是个DP。dp[n][m]表示n个人的时候第m个人能不能活下来。转移的时候想象给人重新编号就好了。 复杂度O(N3).
T6: 暂时未做
T7:GAL (hdu 5220)
题目大意:
给出N个人的属性face,character,magic,求从其中选出一些人要求所有的character都出现过,任意两个的face不一样,所有人的magic异或和为0.求方案数。N<=32.
题解:
1.看到这题应该可以确定是Meet-in-ther-middle思想+Dfs。官方题解写的老长,做法貌似有点奇怪,反正我是没看懂。然后就看Rank1的dzy的代码 打了。好像也不用加什么剪枝。
2.分2次Dfs,使得第一次Dfs的深度都不会超过lim. 这个lim可以自己设定,一般11—15差不多了吧。然后第一次Dfs到头的时候,根据当前拥有的character(用二进制存下)和magic,可以求出另外一半是哪些状态的时候可以和它拼起来。具体实现枚举还缺少的character的子集就好了。
3.第一次AC发现Rank 3了,然后就无耻的修改lim各种shi,shi到Rank 1了。。
T8:Occupation(hdu 5221)
题目大意:
给出一棵树和树上点的权值,要求支持以下3种操作。
1.给路径x-y打上标记,获得之前未打标记的点的权值和的分数。
2.取消x的标记,减去相应的分数。如果x本来就没标记跳过。
3.给x为根的子树打上标记,获得之前未打标记的点的权值和的分数。
题解:
很显然的树链剖分,转化为DFS序和线段树的操作。
操作1.2都是经典用法不多讲。
操作3:一棵子树的DFS序是连续的,所以还是线段树区间的操作。 我之前也不知道这东西,看题解学到了。
T9:Exploration(hdu 5222)
题目大意:
给出一个混合图,求是否存在一个简单环。 |V|,|E|<=106. 无向边也只能走一次。
题解:
1.先考虑无向边,用并查集合连通块,如果存在环,那么ok.
2.在考虑有向边<u,v> 如果u,v在同一个连通块里,那么也存在环.
3.把所有无向边构成的连通块缩成一个点,然后加入有向边,跑一遍拓扑排序判环。
T10:GCD(hdu 5222)
题目大意:
有一个长度为N的数列A,所有元素都是<=109的正整数。给出Q个条件[L,R],d,表示AL-AR的最大公约数为d,然后求满足条件的Ai,要求Ai之和尽可能小。 N,Q<=1000
题解:
对于条件[L,R],d, 我们暂时只能知道AL-AR为d的倍数。所以对AL-AR 和d求个最小公倍数。这样操作完之后,Ai的值保存的就是Ai必须是Ai的倍数。 最后还要检查一下,因为多个条件叠加之后可能会使得gcd变大但不会变小.所以如果符合要求当前解就是和最小的。