05day1 没什么可说,一道模拟水题,两道裸的模板题。05day2 是几天以来最难的一次。

 

圆排列

动态规划

【问题描述】

有 N 个人顺时针围在一圆桌上开会,他们对身高很敏感。 因此决定想使得任意相邻的两人的身高差距最大值最小。 如果答案不唯一,输出字典序最小的排列,指的是身高的排列。

【输入】

输入有多组测试数据。第一行的整数 ng 就表示有 ng 组测试数据(1<=ng<=5)。

每组测试数据格式如下:

第一行: 一个整数 N,3 <= N <= 50

第二行,有个 N 整数, 第 i 个整数表示第 i 个人的身高 hi, 1<=hi<=1000。 按顺指针给出 N个人的身高, 空格分开。

【解题过程】

一开始很自以为是地觉得是贪心。我的错误的贪心策略如下:将身高排序(以下讨论都基于排序的基础上),记为 a[1]..a[n],然后将 a[2] 排在 a[1] 左边,a[3] 排在 a[1] 右边,然后a[4] 排在 a[2] 左边,a[5] 排在 a[3] 右边……这样围成一个圈直到两边在 a[n] 处相遇。

这种方法只能过 2 个点。

然后考虑动态规划。

首先a[1] 和 a[n] 肯定不会排在一起,然后我们可以用相邻交换法证明从 a[1] 到 a[n] 的序列单调增,从 a[n] 到 a[1] 的序列单调减,即最终形态应该是这样:

(简单说明:如果在 a[1] 到 a[n] 的序列中出现了 a[x] > a[x+1],那么交换 a[x] 与 a[x+1] 的位置之后显然得到的是更优而字典序更小的方案,所以从 a[1] 到 a[n] 必然是递增的。)

那么问题就转化为在一个有序的排列中找到两条分别从 a[1] 到 a[n] 的递增的路和从 a[n] 到 a[1] 的递减的路并且要求两条路中途不能有一样的点而路径上相邻点之间的最大身高差最小。

这样看来就是很明显的双线程 DP 了,看做是从 a[1] 出发找两条独立的递增路径,终点为 a[n]。

那么我们就用 f(i, j) 表示一条路走到了点 i,另一条路走到了点 j 时最小的最大身高差(由于 f(i, j)=f(j, i),所以我们规定 i>j),有

当 j=i-1 时,f(i, j) = min{ max{ f(i-1, k), a[i]-a[k]} },1<k<i-1

当 j<i-1 时,f(i, j) = max{ f(i-1, j), a[i]-a[i-1] }

为了处理方便,我们可以令 a[0]=a[1],a[n+1]=a[n],那么有 f(1, 0) = 0,f(2, 1) = a[2]-a[1]

最终结果为 f(n+1, n)

这道题的另一个难点是如何输出方案。为了满足字典序最小,显然我们应该在前半段中尽量取小的编号,但是这样可能会导致后半段无法满足最大差值的约束。那么我们可以反过来考虑后半段,在满足最大差值约束的条件下,尽量往后取大的编号,这样就能保证前半段取到最小的且使得整个解合法的编号。

初次提交 8 分(2/25)。

 

彩色

线段树/离散化

【问题描述】

在直角坐标系上,有 N 个边平行于坐标轴的矩形。你的任务是把其中的 K 个矩形染色,使按次序放下后,可以看见的有色面积最大。可看见的意思就是这一部分没有被后面的矩形覆盖。

你的答案是返回 K 个整数,表示你染色的是哪 K 个矩形。如果有多种答案,输出字典序最小的。

【输入】

第一行两个整数:N,K。

后面有 N 行,每行 4 个整数: x1,y1,x2,y2,分别表示先后各个矩形的左下角坐标和右上角坐标。

【输出】

输出一行,即 K 个整数,表示你染色的矩形序号。

【数据规模】

1<=N<=50; 1<=K<=N。

每个坐标值为[-10000,10000]之间的整数。

【解题过程】

这道题一开始有个细节理解错了:这些矩形是按顺序放下的,也就是说一个矩形只可能被它后面的矩形覆盖而不会被它之前的矩形覆盖。

思路还是比较明确的,计算出每个矩形被覆盖后剩余的面积,取前 k 个大即可。

关键在于求覆盖后的剩余面积。我自己用的是扫描线+线段树,对于每个矩形,把其他矩形与其相交的部分计算出来,然后和普通的扫描线一样做即可。更好的方法是上浮法和离散化,详见国家集训队论文《剖析线段树与矩形切割》。

初次提交 40 分。如上所述理解有误,而且计算相交部分的代码写错了。

 

联络

缩点/连通分量

【问题描述】

神牛 LXX 昨天刚刚满 18 岁,他现在是个成熟的有为男青年。他有 N 个 MM,分别从 1 到 N 标号。

这些 MM 有些是互相认识的。现在,LXX 为了处理和 MM 们复杂的关系,想把他们划分成尽量多的集合,要求任意两个属于不同集合的 MM 都必须互相认识。这样方便交流。现在 LXX 想知道最多可以分成多少个集合,每个集合的人数是多少。

【输入】

输入第一行是两个数 N 和 M。

接下来 M 行,每行两个数,表示这两个 MM 是互相认识的。

【输出】

第一行一个数 S,表示最多有多少个集合。

第二行 S 个数,从小到大,表示每个集合的人数。

【数据规模】

对于 40%的数据,1≤N≤1000,1≤M≤500000;

对于 100%的数据,1≤N≤100000,1≤M≤2000000。

【标程算法】

(好吧其实根本没做这题,看了题解才去做的。)

为了让集合最多,我们尽量把不认识的人分在一组,认识的人分在不同组。如果我们将认识的人用边相连,然后对这个图取反得到它的补图,那么我们只要统计出补图中连通分量的个数即是答案。

但是如果直接用遍历的方式去找连通分量,无论从空间还是时间上都是不可能的。

那么这里我们可以用一种折中的办法:「缩点」。这并不是真正意义上的缩点,而只是将某个点及与其直接相连的点看作同一个点。为了使效果达到最好,我们当然应该选择补图中度最大、即原图中度最小的点。

我们可以分析一下这种做法的可行性:

对于这种方法,最坏情况就是原图中每个点的度相等。

对于极限数据,当 N=10^6,M=2*10^7 时,每个点的度为 2*M/N=40,那么在补图中每个点的度为 10^6-4000=99960,「缩点」之后图中就仅剩 40 个不同的点。

对于特殊数据,当 N=2000,M=2*10^7 时,补图中每个点的度都为 0,无法缩点。此时补图中共 2000 个点,时间和空间上都能承受。

完全可行。

具体做法如下:

  1. 扫一遍找出度最小的顶点 v;
  2. 扫一遍找出与顶点 v 不直接相连的点,用并查集将其合并到顶点 v,并统计这样的点的个数 cnt(原图中不相连则补图中必相连);
  3. 扫一遍得到补图的边权信息(如果不在同一集合内则连一条边);
  4. 需要注意的是,对于已经缩好的顶点 v,补图中 u 到 v 有一条边当且仅当 u 与集合 v 中的任意顶点都不直接相连。

05day2的更多相关文章

随机推荐

  1. 20160722noip模拟赛alexandrali

    [题目大意] 有许多木块, 叠放时, 必须正着叠放, 如图1, 左边两块为合法叠放, 右边为不合法叠放. 图1 一个方块被称为稳定的, 当且仅当其放在最底层, 或其正下方有方块且下方的这个方块的四周都 ...

  2. C# \uxxx Unicode编码解码

    /// <summary> /// Unicode编码 /// </summary> /// <param name="str"></pa ...

  3. Mutex vs Semaphore

    What are the differences between Mutex vs Semaphore? When to use mutex and when to use semaphore? Co ...

  4. Javascript 电子时钟源码

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  5. java基础知识回顾之java集合类-Properties集合

    /** java.lang.Object   |--java.util.Dictionary<K,V>      |--java.util.Hashtable<Object,Obje ...

  6. hdu 1709 The Balance

    母函数的特殊情况,左右两边都可以放,如样例1,2,9 母函数为(1+x+1/x)*(1+x^2+1/x^2)*(1+x^9+1/x^9) 化简为(1+x+x^2)*(1+x^2+x^4)*(1+x^9 ...

  7. PowerDesigner修改设计图中文字的字体大小等样式

    设计图中默认的字体是对英文比较合适的,中文就看不清楚了,特别不美观.但是可以通过修改“Display Preferences”适应我们的汉字. 我使用的PowerDesigner版本是15.1(测试版 ...

  8. excel公式应用大全

    excel公式应用大全 1.ABS函数 函数名称:ABS 主要功能:求出相应数字的绝对值. 使用格式:ABS(number) 参数说明:number代表需要求绝对值的数值或引用的单元格. 应用举例:如 ...

  9. 欧拉工程第66题:Diophantine equation

    题目链接 脑补知识:佩尔方差 上面说的貌似很明白,最小的i,对应最小的解 然而我理解成,一个循环的解了,然后就是搞不对,后来,仔细看+手工推导发现了问题.i从0开始变量,知道第一个满足等式的解就是最小 ...

  10. hdu 4465 Candy

    题解: 由题意得 需要运用: C(m,n)=exp(logC(m,n)) f[]=; ; i<=; i++) f[i]=f[i-]+log(i*1.0); double logC(int m,i ...