模的是这位神犇的代码:Atcoder AGC012F : Prefix Median

题意:

在动态中位数那道题上做了一些改动。给你一个序列a,可以将a重新任意排序,然后对于a序列构造出b序列。

假设a序列有2*n-1个元素,b序列有n个元素。

其中b[i]=Median(a[1],a[2],a[3]...a[2i-1])。求能够构造出多少个不同的b序列。

数据范围:

1<=N<=50,1<=ai<=2N-1

思路:

这道题真的是究极神题...虽然说代码实现比较简单,但是分析的过程是恶心到吐的。

首先,我们需要分析一堆性质:

首先将a序列排序,便于讨论

  1. \(a[i]<=b[i]<=a[2*N-i]\)
  2. \(当i<j时,不存在i使得:b[j]<b[i]<b[j+1]或者是b[j+1]<=b[i]<=b[j]\)

先抛开性质不谈,首先有很明显的一个性质:i从左往右走的时候,假设已经选取的元素的集合为c(c是排好了序的)。每加入两个元素,b[i]的取值的下标在c中只会向左或者是向右移动一格,或者是保持不变。(可以通过枚举法简单证得,即新加入的两个元素x,y都小于b[i-1],或者是都大于b[i+1],或者是一个大于,一个小于的情况)。

然后来看上面的性质。因为求b[i]时的序列中小于等于b[i]至少有i个元素,大于等于b[i]的至少有i个元素,所以说在a数组中的b[i]至少在a[i]~a[2N-i]之间。性质1是没有问题的;

然后是性质2。因为最开始所说的“明显的性质”,所以说b[j]与b[j+1]在已经选取的数字的序列之的位置相差不会超过1,也就是说中间不会间隔任何的数字。但同时还需要注意一点,就是这里是'<'和'>',也就是说是可以取等的,也就是位置保持不变的情况。那么性质2也有了。

接下来就是怎么实现了。

由于开头赋的题解对于代码的部分的具体细节解释的不是很详细,我这里就贸然做一些补充了(〃'▽'〃)

首先定义状态dp[i][L][R]表示现在确定的是b[i],可选元素中小于等于b[i+1]的有L个,大于b[i+1]的有R个。然后考虑转移。转移的话就是枚举b[i]选取的位置,然后删去相应的元素就可以了。然而并没有这么简单!!!具体细节将在代码中进行详细的说明。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100
#define MO 1000000007
using namespace std;
typedef long long LL;
int a[MAXN+5],n;
LL f[MAXN+5][MAXN+5][MAXN+5];
int main()
{
scanf("%d",&n);
for(int i=1;i<=2*n-1;i++)
scanf("%d",&a[i]);
sort(a+1,a+2*n);
f[n][1][0]=1;
//初始状态中,小于等于b[n]的有1个,大于b[n]的有0个(虽然稍微有些违背定义,但是暂且先这样定义吧)
LL t;
for(int i=n-1;i>=1;i--)
{
int al=(a[i]!=a[i+1]),ar=(a[2*n-i]!=+a[2*n-i-1]);
//这里是向两边进行扩展,也就是运用性质1进行扩展
//因为相同的数进行的扩展是没有意义的,所以说需要这样进行能否进行有效的扩展的判断
for(int l=0;l<=2*n-1;l++)
for(int r=0;l+r<=2*n-1;r++)
if(f[i+1][l][r])
{
t=f[i+1][l][r];
for(int dl=1;dl<=l+al;dl++)//选择小于b[i+1]的元素
{
f[i][l+al-dl+1][r+ar+(dl>1)]+=t;
//+al是进行对于L的拓展
//-dl是删去选了的元素与b[i+1]之间的元素
//+1是因为删多了一个,那就是已经选取的b[i],所以说要加回来
//右边+(dl>1)是因为:
//当dl==1的时候,选取的就是b[i+1]这个元素,那就是什么都不会改变的
//当dl>1的时候,选取的就是<b[i+1]中的一个元素,那么b[i+1]就会成为>b[i]中的一个元素,又因为可以取整,所以说要加上去
f[i][l+al-dl+1][r+ar+(dl>1)]%=MO;
}
for(int dr=1;dr<=r+ar;dr++)//选择大于等于b[i+2]的元素
{
f[i][l+al+1][r+ar-dr]+=t;
//左边+1是因为加入b[i]这个可选元素,与上面的比较类似
//右边就是正常的转移,这还比较简单
f[i][l+al+1][r+ar-dr]%=MO;
}
}
}
LL ans=0;
for(int l=0;l<=2*n-1;l++)
for(int r=0;l+r<=2*n-1;r++)
ans=(1LL*ans+1LL*f[1][l][r])%MO;//对于每一个可能的情况都需要计算答案
printf("%lld\n",ans);
return 0;
}

以上只是个人的理解,如果出了什么偏差,还请读者自行脑补ヽ(・ω・´メ)

【AtCoder】【DP】【思维】Prefix Median(AGC012)的更多相关文章

  1. Atcoder Grand Contest 024 E - Sequence Growing Hard(dp+思维)

    题目传送门 典型的 Atcoder 风格的计数 dp. 题目可以转化为每次在序列中插入一个 \([1,k]\) 的数,共操作 \(n\) 次,满足后一个序列的字典序严格大于前一个序列,问有多少种操作序 ...

  2. cf1153D 树形dp+思维

    一千八的题也不会做了呜呜呜 size[u]表示结点u下的叶子结点, 思维:可以想到一个子树对其父亲会有一个消耗值 考虑一个点如果是max,那么其最大值可以是size[u]-p,p是消耗值最小的子树 一 ...

  3. E. The Contest ( 简单DP || 思维 + 贪心)

    传送门 题意: 有 n 个数 (1 ~ n) 分给了三个人 a, b, c: 其中 a 有 k1 个, b 有 k2 个, c 有 k3 个. 现在问最少需要多少操作,使得 a 中所有数 是 1 ~ ...

  4. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  5. codeforces 1140D(区间dp/思维题)

    D. Minimum Triangulation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  6. POJ 1390 Blocks(DP + 思维)题解

    题意:有一排颜色的球,每次选择一个球消去,那么这个球所在的同颜色的整段都消去(和消消乐同理),若消去k个,那么得分k*k,问你消完所有球最大得分 思路:显然这里我们直接用二位数组设区间DP行不通,我们 ...

  7. “玲珑杯”ACM比赛 Round #18---图论你先敲完模板(DP+思维)

    题目链接 DESCRIPTION INPUT OUTPUT SAMPLE INPUT 2 3 2 3 5 7 3 10 3 5 7 SAMPLE OUTPUT 12 26 HINT 官方题解: 代码如 ...

  8. HDU - 5117 Fluorescent(状压dp+思维)

    原题链接 题意 有N个灯和M个开关,每个开关控制着一些灯,如果按下某个开关,就会让对应的灯切换状态:问在每个开关按下与否的一共2^m情况下,每种状态下亮灯的个数的立方的和. 思路1.首先注意到N< ...

  9. Codeforces 407B Long Path(好题 DP+思维)

    题目链接:http://codeforces.com/problemset/problem/407/B 题目大意:一共n+1个房间,一个人从1走到n+1,每次经过房间都会留下一个标记,每个房间有两扇门 ...

随机推荐

  1. elasticsearch篇之mapping

    2018年05月17日 18:01:37 lyzkks 阅读数:444更多 个人分类: Elastic stack   版权声明:文章内容来自于网络和博主自身学习体会,转载请注明出处,欢迎留言大家一起 ...

  2. java 日期格式化

    DateFormat DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间. SimpleDateFormat SimpleDateFormat 是一个以与 ...

  3. 内网ntp时间同步配置

    选择局域网中的一台机器作为ntp服务器,在ntp server上安装并启动ntpd客户端上要关闭ntpd,安装ntpdateCentOS7上这两个软件都是自带的,只需根据需要打开或者关闭.注意客户端机 ...

  4. 教你如何写出高效整洁的 css 代码——css优化(转载)

    css 写起来并不难,但在大型项目中,就变得难以管理,特别是不同的人在 css 书写风格上稍有不同,团队上就更加难以沟通,为此总结了一些如何实现高效整洁的 css 代码原则. css 优化的原则 1. ...

  5. 使用vue-cli创建vue项目

    vue-cli是官方发布的vue.js项目脚手架工具,使用它可以快速创建vue项目,github地址:https://github.com/vuejs/vue-cli 1.安装vue-cli //设置 ...

  6. vmware(1):vmware中的bridge、nat、host-only的区别

    VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式) bridged(桥接模式) 在这种模式下,VMWare虚拟出来的操作系统就 ...

  7. DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果

    前言 上一章我们知道了如何使用几何着色器将顶点通过流输出阶段输出到绑定的顶点缓冲区.接下来我们继续利用它来实现一些新的效果,在这一章,你将了解: 实现公告板效果 Alpha-To-Coverage 对 ...

  8. 第十一节: EF的三种模式(一) 之 DBFirst模式(SQLServer和MySQL两套方案)

    一. 简介 EF连接数据库有三种模式,分别是DBFirst.ModelFirst.CodeFirst,分别适用于不同的开发场景. 该章节,将主要介绍EF的DBFirst连接SQLServer数据库和M ...

  9. 071、如何定制calico网络的IP池(2019-04-16 周二)

    参考https://www.cnblogs.com/CloudMan6/p/7571272.html   在前面的学习中,我们没有特别配置,calico会自动为网络分配subnet,当然我们也可以根据 ...

  10. git中利用rebase来压缩多次提交 ----- 原文:https://blog.csdn.net/itfootball/article/details/44154121

    之前我们用git merge –squash来将分支中多次提交合并到master后,只保留一次提交历史.但是有些提交到github远程仓库中的commit信息如何合并呢? 使用下面的命令,最后一个数字 ...