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变大但不会变小.所以如果符合要求当前解就是和最小的。

原文地址:https://www.cnblogs.com/vb4896/p/4500177.html