题解

将所有物品分成四类,分别为两人共同喜欢的,只有一人喜欢的,没人喜欢的。

首先,先从两人共同喜欢的物品里找出 \(k\) 个,这时,就要从剩余的找出 \(\rm m-k\) 个,而且是最小的。

用一棵权值线段树维护,因为值域太大,所以离散化或动态开点。

之后,指向共同喜欢的物品数量的指针递减,直至 \(0\) 同时增加选取其它物品的量,删除选了的,加上没选的。

因为指针单调递减,所以复杂度为 \(\mathcal O\rm (nlogn)\)

Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
template<typename T>inline void read(T &x) {
ri f=1;x=0;register char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
x=f?x:-x;
}
}
using IO::read;
namespace nanfeng{
#define pb(x) push_back(x)
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
typedef long long ll;
static const int N=2e5+7,INF=1e9;
int v[N],vis1[N],vis2[N],a,b,n,m,k,nm;
ll sum,ans=1e18;
vector<int> lv[3];
inline int cmp(int x,int y) {return v[x]<v[y];}
struct Seg{
#define ls(x) T[x].l
#define rs(x) T[x].r
struct segmenttree{int nm,l,r;ll sum;}T[N<<6];
int st[N<<6],cnt,tot,rt;
inline void up(int x) {
T[x].nm=T[ls(x)].nm+T[rs(x)].nm;
T[x].sum=T[ls(x)].sum+T[rs(x)].sum;
}
inline int New() {return cnt?st[cnt--]:p(tot);}
inline void Del(int &x) {st[p(cnt)]=x;x=0;}
void update(int &x,int p,int l,int r) {
if (!x) x=New();
if (l==r) return (void)(T[x].sum+=p,p(T[x].nm));
int mid(l+r>>1);
if (p<=mid) update(ls(x),p,l,mid);
else update(rs(x),p,mid+1,r);
up(x);
}
void del(int &x,int p,int l,int r) {
if (l==r) {
--T[x].nm,T[x].sum-=p;
if (!T[x].nm) Del(x);
return;
}
int mid(l+r>>1);
if (p<=mid) del(ls(x),p,l,mid);
else del(rs(x),p,mid+1,r);
up(x);
}
ll query(int x,int siz,int l,int r) {
if (!x) return 0;
if (l==r) return (ll)l*(ll)siz;
int mid(l+r>>1);
ll res(0);
if (T[ls(x)].nm>=siz) res+=query(ls(x),siz,l,mid);
else res+=T[ls(x)].sum+query(rs(x),siz-T[ls(x)].nm,mid+1,r);
return res;
}
}T;
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
read(n),read(m),read(k);
if (m<k) {puts("-1");return 0;}
for (ri i(1);i<=n;p(i)) read(v[i]);
read(a);
for (ri i(1),id;i<=a;p(i)) read(id),vis1[id]=1;
read(b);
for (ri i(1),id;i<=b;p(i)) read(id),vis2[id]=1;
for (ri i(1);i<=n;p(i)) {
if (vis1[i]&&vis2[i]) lv[0].pb(i);
else if (vis1[i]) lv[1].pb(i);
else if (vis2[i]) lv[2].pb(i);
else T.update(T.rt,v[i],1,INF);
}
sort(lv[0].begin(),lv[0].end(),cmp);
sort(lv[1].begin(),lv[1].end(),cmp);
sort(lv[2].begin(),lv[2].end(),cmp);
ri bc=cmin((int)lv[0].size(),k),fr=1;
ri siz1=lv[1].size(),siz2=lv[2].size();
if (bc+siz1<k) {puts("-1");return 0;}
if (bc+siz2<k) {puts("-1");return 0;}
for (ri i(0);i<bc;p(i)) sum+=v[lv[0][i]],p(nm);
while(fr+bc<=k) sum+=v[lv[1][fr-1]],sum+=v[lv[2][fr-1]],nm+=2,p(fr);
for (ri i(fr);i<=siz1;p(i)) T.update(T.rt,v[lv[1][i-1]],1,INF);
for (ri i(fr);i<=siz2;p(i)) T.update(T.rt,v[lv[2][i-1]],1,INF);
if (nm>m) {puts("-1");return 0;}
ans=cmin(ans,sum+T.query(T.rt,m-nm,1,INF));
bc-=1,nm-=1;
if (bc>=0) T.update(T.rt,v[lv[0][bc]],1,INF),sum-=v[lv[0][bc]];
while(bc>=0&&bc+siz1>=k&&bc+siz2>=k) {
while(fr+bc<=k) {
sum+=(ll)v[lv[1][fr-1]]+(ll)v[lv[2][fr-1]];
T.del(T.rt,v[lv[1][fr-1]],1,INF);
T.del(T.rt,v[lv[2][fr-1]],1,INF);
nm+=2;
p(fr);
}
if (nm>m) break;
ans=cmin(ans,sum+T.query(T.rt,m-nm,1,INF));
--bc,--nm;
if (bc>=0) T.update(T.rt,v[lv[0][bc]],1,INF),sum-=v[lv[0][bc]];
}
printf("%lld\n",ans);
return 0;
}
}
int main() {return nanfeng::main();}

NOIP 模拟 $23\; \rm 赛$的更多相关文章

  1. NOIP 模拟 $23\; \rm 题$

    题解 \(by\;zj\varphi\) 考虑 \(\rm DP\) 设 \(dp_{k}(S)\) 表示前 \(k\) 个人来后 \(S\) 集合中的苹果都存在的概率是否大于 \(0\) 考虑倒着转 ...

  2. NOIP 模拟 $23\; \rm 联$

    题解 \(by\;zj\varphi\) 区间上的问题,一般都用线段树来解决(但是这题也可以用 \(\rm ODT\)) 对于每段段区间设置三个参数,分别表示这个区间是否只有 \(1\) 或 \(0\ ...

  3. noip模拟23[联·赛·题]

    \(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...

  4. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  5. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

  6. [SinGuLaRiTy] NOIP互测模拟赛

    [SinGuLaRiTy-1045] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 源文件名 输入输出文件 时间限制 内存限制 淘气的cch ...

  7. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  8. 2021.5.22 noip模拟1

    这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...

  9. NOIP 模拟 $36\; \rm Cicada 拿衣服$

    题解 \(by\;zj\varphi\) 发现右端点固定时,左端点的 \(min-max\) 单调递减,且对于 \(or\) 和 \(and\) 相减,最多有 \(\rm2logn\)个不同的值,且相 ...

随机推荐

  1. hugo + nginx 搭建博客记录

    作为一个萌新Gopher,经常逛网站能看到那种极简的博客,引入眼帘的不是花里胡哨的图片和样式,而是黑白搭配,简简单单的文章标题,这种风格很吸引我.正好看到煎鱼佬也在用这种风格的博客,于是卸载了我的wo ...

  2. get和post两种表单提交方式的区别

    今天看到一篇博客谈论get和post区别,简单总结一下https://www.cnblogs.com/logsharing/p/8448446.html 要说两者的区别,接触过web开发的人基本上都能 ...

  3. GO系列-ini文件处理

    gopkg.in/ini.v1 配置加载 创建一个空的配置 cfg := ini.Empty() 直接加载存在的配置文件,如果文件不存在就会报错 cfg, err := ini.Load(" ...

  4. k8s之deployment详解

    Deployment介绍 为了更好地解决服务编排的问题,k8s在V1.2版本开始,引入了deployment控制器,值得一提的是,这种控制器并不直接管理pod, 而是通过管理replicaset来间接 ...

  5. python 得到汉字的拼音

    import pypinyin # 不带声调的(style=pypinyin.NORMAL) def pinyin(word): s = '' for i in pypinyin.pinyin(wor ...

  6. Java基础00-多线程28

    1. 实现多线程 1.1 进程 1.2 线程 1.3 多线程的实现方式(方式一:继承Thread类) 代码示例:定义类MyThread: //1:定义一个类MyThread继承Thread类 publ ...

  7. 传统.NET 4.x应用容器化体验(4)

    上一篇我们试着将.NET 4.x的镜像推送到harbor私有镜像仓库,本篇我们来使用一下阿里云的镜像仓库服务并了解一下携程的实践. 1 关于阿里云镜像仓库 阿里云容器镜像服务(简称 ACR)是面向容器 ...

  8. springboot-5-持久层技术

    整合mybatis 流程: 导入依赖: 除了mybaits还有mysql和jdbc依赖 <!--mybatis--> <dependency> <groupId>o ...

  9. Java 并发之 Fork/Join 框架

    什么是 Fork/Join 框架 Fork/Join 框架是一种在 JDk 7 引入的线程池,用于并行执行把一个大任务拆成多个小任务并行执行,最终汇总每个小任务结果得到大任务结果的特殊任务.通过其命名 ...

  10. SpringCloud学习之【Eureka实现服务注册与发现】

    这段时间开始整理之前的SpringCloud实践笔记,这里感谢翟永超大佬的文章SpringCloud从入门到精通的指导. 项目结构 服务注册中心 注意: 1.SpringCloud与SpringBoo ...