题目传送门:LOJ #3158

题意简述:

给定两个长度为 \(n\) 的正整数序列 \(a,b\),要求在每个序列中都选中 \(K\) 个下标,并且要保证同时在两个序列中都被选中的下标至少有 \(L\) 个,使得选中的下标对应的数的总和最大。

题解:

题目相当于要求在两个序列中选出 \(K\) 对数,不妨一对一对地选。

有个结论是说,上一步的最优决策一定不会再反悔,就是已经选的不会再撤销。

然后做完了,用堆维护一些东西,精细实现就好了。

下面是代码,复杂度 \(\mathcal{O}\left(\sum n\log n\right)\)。

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cctype> #define fi first
#define se second
#define mp std::make_pair
typedef long long LL;
typedef std::pair<int, int> pii;
typedef std::priority_queue<pii> PQ;
const int MN = 200005; inline void read(int &x) {
x = 0; static char ch;
while (!isdigit(ch = getchar())) ;
while (x = x * 10 + (ch & 15), isdigit(ch = getchar()));
}
inline void write(LL x) {
static char st[15];
static char *t = st;
while (x) *t++ = (x % 10) | 48, x /= 10;
while (t != st) putchar(*--t);
putchar('\n');
} int N, K, L;
int A[MN], B[MN];
bool vA[MN], vB[MN];
PQ A0, B0, A1, B1, C;
LL Ans; int main() {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
int T; scanf("%d", &T);
while (T--) {
Ans = 0;
while (!A0.empty()) A0.pop();
while (!B0.empty()) B0.pop();
while (!A1.empty()) A1.pop();
while (!B1.empty()) B1.pop();
while (!C.empty()) C.pop();
read(N), read(K), read(L);
for (int i = 1; i <= N; ++i) read(A[i]);
for (int i = 1; i <= N; ++i) read(B[i]);
for (int i = 1; i <= N; ++i) {
vA[i] = vB[i] = 0;
A0.push(mp(A[i], i));
B0.push(mp(B[i], i));
C.push(mp(A[i] + B[i], i));
}
int left = K - L;
for (int cnt = 1; cnt <= K; ++cnt) {
while (vA[A0.top().se]) A0.pop();
while (vB[B0.top().se]) B0.pop();
if (left) {
pii a = A0.top(), b = B0.top();
A0.pop(), B0.pop();
Ans += a.fi + b.fi;
int ap = a.se, bp = b.se;
vA[ap] = vB[bp] = 1;
if (ap == bp) C.pop();
else {
--left;
if (vB[ap]) ++left, A1.pop();
else B1.push(mp(B[ap], ap));
if (vA[bp]) ++left, B1.pop();
else A1.push(mp(A[bp], bp));
}
}
else {
pii c0 = C.empty() ? mp(0, 0) : C.top();
while (vA[c0.se] || vB[c0.se])
C.pop(), c0 = C.empty() ? mp(0, 0) : C.top();
pii a0 = A0.top(), b0 = B0.top();
pii a1 = A1.empty() ? mp(-b0.fi, 0) : A1.top();
pii b1 = B1.empty() ? mp(-a0.fi, 0) : B1.top();
int a = a1.fi + b0.fi;
int b = b1.fi + a0.fi;
if (c0.fi >= a && c0.fi >= b)
Ans += c0.fi, vA[c0.se] = vB[c0.se] = 1;
else if (a >= b) {
Ans += a;
A1.pop(), B0.pop(), vA[a1.se] = vB[b0.se] = 1;
if (b1.se == b0.se) B1.pop(), ++left;
else A1.push(mp(A[b0.se], b0.se));
}
else {
Ans += b;
B1.pop(), A0.pop(), vB[b1.se] = vA[a0.se] = 1;
if (a1.se == a0.se) A1.pop(), ++left;
else B1.push(mp(B[a0.se], a0.se));
}
}
} write(Ans);
}
return 0;
}

证明?不要问我证明啊!其实仔细分析一下应该是能证出来的,再不行就先套个费用流模型。

LOJ 3158: 「NOI2019」序列的更多相关文章

  1. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

  2. loj #2051. 「HNOI2016」序列

    #2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na​1​​,a​2​​,⋯,a​n​​,记为 a[1: ...

  3. LOJ 3160: 「NOI2019」斗主地

    题目传送门:LOJ #3160. 简要题意: 有一个长度为 \(n\) 的序列 \(a\),初始时 \(a_i=i\) 或 \(a_i=i^2\),这取决于 \(\mathrm{type}\) 的值. ...

  4. LOJ #2183「SDOI2015」序列统计

    有好多好玩的知识点 LOJ 题意:在集合中选$ n$个元素(可重复选)使得乘积模$ m$为$ x$,求方案数对$ 1004535809$取模 $ n<=10^9,m<=8000且是质数,集 ...

  5. LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分

    题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...

  6. LOJ 3159: 「NOI2019」弹跳

    题目传送门:LOJ #3159. 题意简述: 二维平面上有 \(n\) 个整点,给定每个整点的坐标 \((x_i,y_i)\). 有 \(m\) 种边,第 \(i\) 种边从 \(p_i\) 号点连向 ...

  7. LOJ 3156: 「NOI2019」回家路线

    题目传送门:LOJ #3156. 题意简述: 有一张 \(n\) 个点 \(m\) 条边的有向图,边有两个权值 \(p_i\) 和 \(q_i\)(\(p_i<q_i\))表示若 \(p_i\) ...

  8. 「NOI2019」序列

    NKOJ卡常卡不过QAQ description 给两个A,B序列,让你分别在A,B中各选k个数,其中至少有L对下标相等. Solution 把问题转化为至多选n-K对下标不同的对. 配对问题就用费用 ...

  9. loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)

    题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...

随机推荐

  1. CF1217E Sum Queries? (线段树)

    完了,前几天才说 edu 的 DEF 都不会,现在打脸了吧 qwq 其实在刚说完这句话 1min 就会了 D,3min 就会了 E 发现,对于大小 \(\ge 3\) 的不平衡集合,它至少有一个大小为 ...

  2. MySQL学习笔记2————基础篇记录

    这里以实验楼的数据库来记录,如有侵犯实验楼权益,请联系本人,必定删除 在此感谢实验楼提供的免费教程 MySQL 基础课程_SQL - 实验楼 一. 表project employee 任务:想要知道名 ...

  3. Python __name__的使用

    __name__是什么 * __开头代表是系统变量; * __name__ 是标识模块名字的系统变量. 当前模块是主模块时, 模块名就是"__main__"; 当模块是被调用(im ...

  4. Redis数据结构及常用命令(草稿)

    通用命令 数据类型 string 字符 list 列表 set 集合 zset 有序集合 hash 散列(字典中的字典) bitmap 位图 hyperloglog

  5. [原创]浅谈在创业公司对PMF的理解

    [原创]浅谈在创业公司对PMF的理解 在创业时,大多数人都常谈一个词叫"MVP“,但PMF谈的比较少,PMF在创业公司尤为重要,以下谈谈个人一些看法. 1.什么是PMF? 创业公司:一种是找 ...

  6. MySQL-InnoDB-MVCC多版本并发控制

    一.MySQL可重复读级别下,因为MVCC引起的BUG,下图1为相应的Java代码,其中事务1的生命周期最长,循环开启的事务2.3.4...与事务1并行 ,数据的读取只会成功一次,后面的读不到新增数据 ...

  7. Java连载12-继承开发环境&long类型

    一.集成开发环境(Integrated Develop Environment,简称IDE) 1.什么是集成开发环境 (1)集成开发环境可以使软件开发变得更简单 (2)没有IDE工具: i.需要安装J ...

  8. Beta冲刺(9/7)——2019.5.31

    作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Beta冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 队 ...

  9. numpy 数组增加列,增加行的函数:column_stack,row_stack

    def fun_ndarray(): a = [[1,2,7], [-6,-2,-3], [-4,-8,-55] ] b = [3,5,6] a = np.array(a) b = np.array( ...

  10. 如何防止短信API接口遍历

    短信API接口在web中得到越来越多的应用,如用户注册,登录,密码重置等业务模块都会使用手机验证码进行身份验证.一般情况下,我们会采用这样的安全策略,将短信发送频率限制在正常的业务流控范围内,比如,一 ...