题目链接

https://loj.ac/problem/6502

题解

中间一档部分分提示我们将所有的 \(w_i\) 排序。

考虑如果我们能构造出这样一个 \(w_i\) 的序列,使得该序列满足:对于任意的 \(i(1 \leq i \leq n)\),所有的 \(j(1 \leq j < i)\) 都满足 \(w_i + w_j \geq m\) 或者所有的 \(j(1 \leq j < i)\) 都满足 \(w_i + w_j < m\),那么我们就可以使用动态规划求解。

具体地,设 \(f_{i, j}\) 表示处理到了 \(w_i\),且 \(A\) 队中已有 \(j\) 个元素能得到的最大贡献值。若 \(w_i\) 满足对于任意 \(j(1 \leq j < i)\) 有 \(w_i + w_j \geq m\),那么考虑将 \(w_i\) 放入 \(A\) 队,则 \(w_i\) 与前面所有放入 \(B\) 队的 \(i - j\) 个元素都能配合默契,因此有 \(f_{i, j} = f_{i - 1, j - 1} + i - j\);考虑放入 \(B\) 队,则 \(w_i\) 与前面所有放入 \(A\) 队中的 \(j\) 个元素都能配合默契,因此有 \(f_{i, j} = f_{i - 1, j} + j\),最终答案在两者间取 \(\rm max\)。若 \(w_i\) 满足对于任意 \(j(1 \leq j < i)\) 有 \(w_i + w_j < m\),由于无论放入 \(A\) 队还是 \(B\) 队都不能造成贡献,因此转移为 \(f_{i, j} = {\rm max}\{f_{i - 1, j - 1}, f_{i - 1, j}\}\)。求方案数在转移 \(f\) 时一起统计即可。

现在的问题是如何构造这个序列。

我们先将 \(w\) 从小到大排序,发现若 \(w_1 + w_n \geq m\),那么对于任意的 \(j(1 \leq j < n)\) 均满足 \(w_j + w_n \geq m\);若 \(w_1 + w_n < m\),那么对于任意的 \(j(1 < j \leq n)\) 均满足 \(w_1 + w_j < m\),但依然有可能存在 \(j(1 \leq j < n)\) 满足 \(w_j + w_n \geq m\)。

因此,我们可以思考如下算法:对于按从小到大排序后得到的区间 \([l, r]\),若满足 \(w_l + w_r \geq m\),那么弹出 \(w_r\),处理区间 \([l, r - 1]\),否则弹出 \(w_l\),处理区间 \([l + 1, r]\)。每次我们将弹出的数放到一个新的数组 \(p\) 的最左端,那么可以证明,得到的 \(p\) 数组就能够满足我们所需要的性质。

我们求出数组 \(p\) 后,就能够通过 dp 在 \(O(n^2)\) 的时间内解决此题了。

代码

#include<bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define debug(...) fprintf(stderr, __VA_ARGS__) typedef long long ll;
typedef long double ld;
typedef unsigned int uint;
typedef pair<int, int> pii;
typedef unsigned long long ull; template<typename T> inline void read(T& x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
} template<typename T> inline bool checkMax(T& a, const T& b) {
return a < b ? a = b, true : false;
} template<typename T> inline bool checkMin(T& a, const T& b) {
return a > b ? a = b, true : false;
} const int N = 2e3 + 10, mod = 1e9 + 7; inline void add(int& x, int y) {
x = (x + y) % mod;
} int n, m, a[N], all[N], f[N][N], g[N][N]; int main() {
read(n), read(m);
for (register int i = 1; i <= n; ++i) {
read(a[i]);
}
sort(a + 1, a + 1 + n);
int l = 1, r = n;
for (register int i = n; i; --i) {
if (a[l] + a[r] >= m) {
all[i] = 1, --r;
} else {
all[i] = 0, ++l;
}
}
int ans = 0;
g[0][0] = 1;
for (register int i = 1; i <= n; ++i) {
for (register int j = 0; j <= i; ++j) {
if (j ^ i) {
int v = f[i - 1][j] + (all[i] ? j : 0);
if (v > f[i][j]) {
f[i][j] = v, g[i][j] = g[i - 1][j];
} else if (v == f[i][j]) {
add(g[i][j], g[i - 1][j]);
}
} if (j) {
int v = f[i - 1][j - 1] + (all[i] ? i - j : 0);
if (v > f[i][j]) {
f[i][j] = v, g[i][j] = g[i - 1][j - 1];
} else if (v == f[i][j]) {
add(g[i][j], g[i - 1][j - 1]);
}
}
checkMax(ans, f[i][j]);
}
}
int res = 0;
for (register int i = 0; i <= n; ++i) {
if (f[n][i] == ans) {
add(res, g[n][i]);
}
}
printf("%d %d\n", ans, res);
return 0;
}

LOJ6502. 「雅礼集训 2018 Day4」Divide(构造+dp)的更多相关文章

  1. Loj #6503. 「雅礼集训 2018 Day4」Magic

    Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...

  2. LOJ#6503.「雅礼集训 2018 Day4」Magic[容斥+NTT+启发式合并]

    题意 \(n\) 张卡牌 \(m\) 种颜色,询问有多少种本质不同的序列满足相邻颜色相同的位置数量等于 \(k\). 分析 首先本质不同不好直接处理,可以将同种颜色的卡牌看作是不相同的,求出答案后除以 ...

  3. 【loj#6503.】「雅礼集训 2018 Day4」Magic(生成函数+容斥)

    题面 传送门 题解 复杂度比较迷啊-- 以下以\(n\)表示颜色总数,\(m\)表示总的卡牌数 严格\(k\)对比较难算,我们考虑容斥 首先有\(i\)对就代表整个序列被分成了\(m-i\)块互不相同 ...

  4. LOJ6503. 「雅礼集训 2018 Day4」Magic(容斥原理+NTT)

    题目链接 https://loj.ac/problem/6503 题解 题中要求本质不同的序列数量,不太好搞.我们考虑给相同颜色的牌加上编号,这样所有牌都不相同.那么如果我们求出了答案,只需要将答案除 ...

  5. 「雅礼集训 2018 Day2」农民

    传送门 Description  「搞 OI 不如种田.」 小 D 在家种了一棵二叉树,第 ii 个结点的权值为 \(a_i\). 小 D 为自己种的树买了肥料,每天给树施肥. 可是几天后,小 D 却 ...

  6. 2018.10.27 loj#6035. 「雅礼集训 2017 Day4」洗衣服(贪心+堆)

    传送门 显然的贪心题啊...考试没调出来10pts滚了妙的一啊 直接分别用堆贪心出洗完第iii件衣服需要的最少时间和晾完第iii件衣服需要的最少时间. 我们设第一个算出来的数组是aaa,第二个是bbb ...

  7. 【loj - 6516】「雅礼集训 2018 Day11」进攻!

    目录 description solution accepted code details description 你将向敌方发起进攻!敌方的防御阵地可以用一个 \(N\times M\) 的 \(0 ...

  8. LOJ #6509. 「雅礼集训 2018 Day7」C

    神仙题 LOJ #6509 题意 给定一棵树,点权为0/1,每次随机一个点(可能和之前所在点相同)走到该点并将其点权异或上1 求期望的移动距离使得所有点点权相同 题解 根本不会解方程 容易发现如果一个 ...

  9. loj 6037 「雅礼集训 2017 Day4」猜数列 - 动态规划

    题目传送门 传送门 题目大意 有一个位置数列,给定$n$条线索,每条线索从某一个位置开始,一直向左或者向右走,每遇到一个还没有在线索中出现的数就将它加入线索,问最小的可能的数列长度. 依次从左到右考虑 ...

随机推荐

  1. css一div内文字居中

    在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...

  2. p2148 [SDOI2009]E&D

    传送门 分析 https://www.luogu.org/blog/flashblog/solution-p2148 代码 #include<bits/stdc++.h> using na ...

  3. 单个控件textbox只支持在英文状态下输入所需的字符串

    也就是它的属性: Imemode的属性 设置成off就可以了 ,就不会受到所输入的中文汉字了.

  4. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(3):常用动态代理之JDK动态代理、CGLIB动态代理

    一.动态代理的理解 动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问.        先来谈谈什么是代理模式.        假设这样一个场景:你的公司是一家软件 ...

  5. 国外物联网平台(8):Telit

    国外物联网平台(8) ——Telit 马智 定位 We Bring IoT to Life Telit提供世界上最全面的高性能物联网模块.连接服务和软件. 产品体系 模块 Telit提供丰富专业的物联 ...

  6. Go语言最佳实践——面向对象

    对于接口,应使用组合而非继承的方式扩展: 对于结构体,应定义独立的结构体,而非用嵌套模拟继承. 值接收者和指针接收者: 1.对于不可变类型创建只接受值接收者的方法,而为可变的类型创建接受指针接收者的方 ...

  7. .net core webapi 文件上传在 Swagger 文档中的有好提示处理

    前提: 需要nuget   Swashbuckle.AspNetCore 我暂时用的是  4.01 最新版本: 描述:解决 .net core webapi 上传文件使用的是 IFormFile,在S ...

  8. 以太坊系列之二: 单调时间monotime-以太坊源码学习

    在程序中需要测量时间时最好使用monotime.Now()而不是time.Now(),相比之下前者更准确. 来个示例: func main() { var start, elapsed time.Du ...

  9. 家用wifi信号覆盖增强扩展实用指南

    家用wifi信号覆盖增强扩展实用指南 现在网上很多号称穿墙王的无线路由器,但是一般用起来效果都不理想,其实最主要的原因还是家里面一般每个房间不大,但是墙比较多.并且一般也没有一个所谓的中心点放置路由器 ...

  10. 「TJOI2013」循环格

    题目链接 戳我 \(Solution\) 我们观察发现循环格要满足每个点的入度都为\(1\) 证明: 我们假设每个点的入读不一定为\(1\),那么必定有一个或多个点的入度为0,那么则不满足循环格的定义 ...