NKOJ卡常卡不过QAQ

description

给两个A,B序列,让你分别在A,B中各选k个数,其中至少有L对下标相等。

Solution

把问题转化为至多选n-K对下标不同的对。

配对问题就用费用流……

同坐标A,B两两连边。

然后有一个虚拟点,所有点A连向它,它又连向所有点B。代表不同下标的点配对。这个点还要拆成两个虚拟点(中间容量为n-K)。

接着模拟费用流

(注意这次的模拟费用流的反悔功能是利用贪心实现的)

过程中记录\(flow\)为剩下的流量(还能选不同下标的对数)

1.直接选两个下标相等的点\(a_i\)和\(b_i\)

2.直接选两个下标不等的点\(a_i\)和\(b_j\) flow--

令\(a'_i\)表示\(a_i\)没选\(b_i\)选了,同理\(b'_i\)表示\(b_i\)没选\(a_i\)选了(总之就是相对应下标选了)

3.选\(a'_i\)和\(b_j\),配对后flow--,但是发现可以做到\(a'_i\)配\(b_i\),然后\(b_j\)替补原来\(b_i\)配对的点。flow++(相当于flow不变化)

4.(3的a,b颠倒)选\(b'_i\)和\(a_j\),同3

5.选\(a'_i\)和\(b'_j\),断掉\(b_i\)和\(a_j\)的联系,发现i,j都可以分别满足a,b配对。flow++

注意在优先选值最大的以外,优先选5,最后选2(flow相当于第二关键字)

过程用5个堆维护就好了,分别维护\(a_i\) , \(b_i\) , \(a_i+b_i\) , \(a'_i\) , \(b'_i\)

中间需要删除用标记就好。

然后\(a'_i\)和\(b'_i\)都是对立点标记后,才加进去的。

我还想过一个贪心优化,就是a,b先从大到小排序,然后分别找前k大,看看是否存在下标相同的a,b点对,存在就直接取了,不过没什么用,因为排序费时。

最后为什么我跑的这么慢,呜呜……

code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return x*f;
}
void print(ll x) {
if(x>9) print(x/10);
*O++=x%10+'0';
}
int n,K,L,a[N],b[N],flow;
ll inf=1e18;
bool ua[N],ub[N];
struct node {
int p;ll w;
bool operator<(const node &u) const{return w<u.w;}
};
struct nd {
int p;ll w;
bool operator<(const nd &u) const{return w>u.w;}
}A[N],B[N];
priority_queue<node> Q1,Q2,Q3,Q4,Q5;
void _clear() {
while(Q1.size()>1&&ua[Q1.top().p]) Q1.pop();
while(Q2.size()>1&&ub[Q2.top().p]) Q2.pop();
while(Q3.size()>1&&(ua[Q3.top().p]||ub[Q3.top().p]))Q3.pop();
}
void Clear() {
while(Q1.size()>1) Q1.pop();
while(Q2.size()>1) Q2.pop();
while(Q3.size()>1) Q3.pop();
while(Q4.size()>1) Q4.pop();
while(Q5.size()>1) Q5.pop();
for(int i=1;i<=n;i++) ua[i]=ub[i]=0;
}
#define u1 Q1.top().w
#define u2 Q2.top().w
#define u3 Q3.top().w
#define u4 Q4.top().w
#define u5 Q5.top().w
ll sum;
bool flag=0;
//void init() { //没用的贪心优化
// for(int i=1;i<=n;i++) A[i]=(nd){i,a[i]},B[i]=(nd){i,b[i]};
// sort(A+1,A+1+n);
// sort(B+1,B+1+n);
// for(int i=1;i<=L;i++) ua[A[i].p]=ub[B[i].p]=1;
// for(int i=1;i<=n&&L;i++) {
// if(ua[i]&&ub[i]) {sum+=a[i]+b[i];L--;K--;}
// else {
// ua[i]=ub[i]=0;Q1.push((node){i,a[i]});Q2.push((node){i,b[i]});Q3.push((node){i,a[i]+b[i]});
// }
// }
// if(!L) {
// for(int i=1,j=1;i<=n&&j<=K;i++) if(!ua[A[i].p])sum+=A[i].w;
// for(int i=1,j=1;i<=n&&j<=K;i++) if(!ub[B[i].p])sum+=B[i].w;
// flag=1;print(sum);*O++='\n';
// }
//}
void solve() {
for(int i=1;i<=n;i++) {Q1.push((node){i,a[i]});Q2.push((node){i,b[i]});Q3.push((node){i,a[i]+b[i]});}
int flow=L<=0?1e9:K-L;
for(int i=1;i<=K;i++) {
_clear();
ll w1=flow?u1+u2:-inf;
ll w2=u3;
ll w3=u4+u2;
ll w4=u5+u1;
ll w5=u4+u5;
ll mx=max(max(w1,w2),max(w3,w4));
if(w5>=mx) {flow++;sum+=w5;ua[Q4.top().p]=ub[Q5.top().p]=1;Q4.pop();Q5.pop();}
else if(w4==mx) {
sum+=w4;int x=Q1.top().p;ua[x]=ub[Q5.top().p]=1;
if(!ub[x])Q5.push((node){x,b[x]});
Q1.pop();Q5.pop();
}
else if(w3==mx) {
sum+=w3;int y=Q2.top().p;ua[Q4.top().p]=ub[y]=1;
if(!ua[y])Q4.push((node){y,a[y]});
Q4.pop();Q2.pop();
}
else if(w2==mx) {
sum+=w2;ua[Q3.top().p]=ub[Q3.top().p]=1;
Q3.pop();
}
else {
int x=Q1.top().p,y=Q2.top().p;
sum+=w1;flow--;ua[x]=ub[y]=1;
if(!ub[x]) Q5.push((node){x,b[x]});
if(!ua[y]) Q4.push((node){y,a[y]});
Q1.pop();Q2.pop();
}
}
print(sum);*O++='\n';
}
int main() {
Q1.push((node){-1,-inf}),Q2.push((node){-1,-inf}),Q3.push((node){-1,-inf}),Q4.push((node){-1,-inf}),Q5.push((node){-1,-inf});
int T=read();
while(T--) {
n=read(),K=read(),L=read();
for(int i=1;i<=n;i++) {a[i]=read();}
for(int i=1;i<=n;i++) {b[i]=read();}
sum=flag=0;
// if(L>=n/2)init();
if(!flag)solve();
Clear();
}
fwrite(obuf,O-obuf,1,stdout);
return 0;
}

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

  1. LOJ 3158: 「NOI2019」序列

    题目传送门:LOJ #3158. 题意简述: 给定两个长度为 \(n\) 的正整数序列 \(a,b\),要求在每个序列中都选中 \(K\) 个下标,并且要保证同时在两个序列中都被选中的下标至少有 \( ...

  2. loj3161「NOI2019」I 君的探险(随机化,整体二分)

    loj3161「NOI2019」I 君的探险(随机化,整体二分) loj Luogu 题解时间 对于 $ N \le 500 $ 的点,毫无疑问可以直接 $ O(n^2) $ 暴力询问解决. 考虑看起 ...

  3. Loj #3059. 「HNOI2019」序列

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

  4. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  5. AC日记——「SDOI2017」序列计数 LibreOJ 2002

    「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 201704 ...

  6. loj #2051. 「HNOI2016」序列

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

  7. 「JSOI2014」序列维护

    「JSOI2014」序列维护 传送门 其实这题就是luogu的模板线段树2,之所以要发题解就是因为学到了一种比较NB的 \(\text{update}\) 的方式.(参见这题) 我们可以把修改操作统一 ...

  8. 「BZOJ1251」序列终结者 (splay 区间操作)

    题面: 1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 5367  Solved: 2323[Submit][Status][D ...

  9. 「LuoguP1430」 序列取数(区间dp

    题目描述 给定一个长为n的整数序列(n<=1000),由A和B轮流取数(A先取).每个人可从序列的左端或右端取若干个数(至少一个),但不能两端都取.所有数都被取走后,两人分别统计所取数的和作为各 ...

随机推荐

  1. react 移动端 兼容性问题和一些小细节

    react 移动端 兼容性问题和一些小细节 使用 ES6 的浏览器兼容性问题 react 对低版本的安卓webview 兼容性 iOS下 fixed与软键盘的问题 onClick 阻止冒泡 meta对 ...

  2. H5新增API

    H5新增API 选择器 querySelector()和querySelectorAll(),参数都是css选择器,前者返回符合条件的第一个匹配的元素,如果没有则返回Null,后者返回符合筛选条件的所 ...

  3. ES6-11学习笔记--数组遍历

    ES5中数组遍历方式: for循环 forEach():没有返回值,只是针对每个元素调用func map():返回新的Array,每个元素为调用func的结果 filter():返回符合func条件的 ...

  4. activity-alias属性的使用

    activity-alias是Android里为了重复使用Activity而设计的.1. 含义和作用:         对于activity-alias标签,它有一个属性叫android:targen ...

  5. Mybatis-Dao层实现(通过代理方式)

    1.代理方式开发是主流 2.Mapper接口开发方法只需要编写Mapper接口(相当于Dao接口),然后由Mybatis根据接口创建动态代理对象 Mapper接口开发需要遵循以下规范 一一对应 Use ...

  6. rabbitmq简单运用

    <?php /** * 生产者 */ $connection = new AMQPConnection([ 'host' => '192.168.23.130', 'port' => ...

  7. Fastjsonfan反序列链学习前置知识

    Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...

  8. springmvc03-restful和控制器

    一.控制器Controller 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现. 控制器负责解析用户的请求并将其转换为一个模型. 在Spring MVC中一个控制器类可以包含 ...

  9. ABP应用开发(Step by Step)-上篇

    本文主要通过逐步构建一个CRUD示例程序来介绍 ABP 框架的基础知识.它涉及到应用开发的多个方面.在本章结束时,您将了解ABP 框架的基本开发方式.建议入门人员学习,老手不要浪费您宝贵时间.  创建 ...

  10. Bugku练习题---MISC---FileStoragedat

    Bugku练习题---MISC---FileStoragedat flag:bugku{WeChatwithSteg0} 解题步骤: 1.观察题目,下载附件 2.下载后发现是一个后缀名为.dat的文件 ...