将选取的$A$看成左括号,$B$看成右括号,那么答案是一个合法的括号序列。

那么只要重复取出$k$对价值最小的左右括号,保证每时每刻都是一个合法的括号序列即可。

将$($看成$1$,$)$看成$-1$,设$s[]$为前缀和。

如果当前取出的是$()$,那么对前缀和的影响为$[A,B-1]$区间加$1$。

如果当前取出的是$)($,那么对前缀和的影响为$[B,A-1]$区间减$1$,所以这种情况需要满足区间$s$的最小值不为$0$。

考虑用线段树维护这个序列,线段树上每个节点维护以下信息:

va:$A\leq B$情况的最优解。

vb:$A>B$情况的最优解,且满足$[A,B-1]$的区间$s$最小值大于当前区间的$s$最小值。

vc:$A>B$情况的最优解。

aa:区间内代价最小的$A$。

ab:区间内代价最小的$B$。

ba:区间内代价最小的$A$,满足$[st,A-1]$的区间$s$最小值大于区间$s$最小值。

bb:区间内代价最小的$B$,满足$[B,en]$的区间$s$最小值大于区间$s$最小值。

vm:区间$s$最小值。

tag:区间增量标记。

为了方便维护,可以考虑增加第$0$项,$A[0]=B[0]=inf$。

那么$[0,n]$区间的$vb$必定满足区间最小值不为$0$,然后贪心选取$k$次即可求出最优解。

时间复杂度$O(k\log n)$。

#include<cstdio>
const int N=500010,M=1050000,inf=1000000010;
long long ans;
int n,k,i,j,A[N],B[N],aa[M],ab[M],ba[M],bb[M],vm[M],tag[M];
struct P{
int x,y;
P(){}
P(int _x,int _y){x=_x,y=_y;}
P operator+(const P&b){return A[x]+B[y]<A[b.x]+B[b.y]?*this:b;}
}va[M],vb[M],vc[M],t;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add1(int x,int p){vm[x]+=p;tag[x]+=p;}
inline void pb(int x){if(tag[x])add1(x<<1,tag[x]),add1(x<<1|1,tag[x]),tag[x]=0;}
inline void up(int x){
int l=x<<1,r=l|1;
va[x]=va[l]+va[r]+P(aa[l],ab[r]);
vc[x]=vc[l]+vc[r]+P(aa[r],ab[l]);
vb[x]=vb[l]+vb[r];
aa[x]=A[aa[l]]<A[aa[r]]?aa[l]:aa[r];
ab[x]=B[ab[l]]<B[ab[r]]?ab[l]:ab[r];
if(vm[l]<vm[r]){
vb[x]=vb[x]+vc[r]+P(aa[r],bb[l]);
ba[x]=ba[l];
bb[x]=B[ab[r]]<B[bb[l]]?ab[r]:bb[l];
vm[x]=vm[l];
}
if(vm[l]>vm[r]){
vb[x]=vb[x]+vc[l]+P(ba[r],ab[l]);
ba[x]=A[aa[l]]<A[ba[r]]?aa[l]:ba[r];
bb[x]=bb[r];
vm[x]=vm[r];
}
if(vm[l]==vm[r]){
vb[x]=vb[x]+P(ba[r],bb[l]);
ba[x]=ba[l];
bb[x]=bb[r];
vm[x]=vm[l];
}
}
void build(int x,int a,int b){
if(a==b){
va[x]=vc[x]=P(a,a),vb[x]=P(0,0);
aa[x]=ab[x]=ba[x]=a;
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void add(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){add1(x,p);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)add(x<<1,a,mid,c,d,p);
if(d>mid)add(x<<1|1,mid+1,b,c,d,p);
up(x);
}
void change(int x,int a,int b,int c){
if(a==b)return;
pb(x);
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c);else change(x<<1|1,mid+1,b,c);
up(x);
}
int main(){
read(n),read(k);
for(i=1;i<=n;i++)read(A[i]);
for(i=1;i<=n;i++)read(B[i]);
A[0]=B[0]=inf;
build(1,0,n);
while(k--){
t=va[1]+vb[1],i=t.x,j=t.y,ans+=A[i]+B[j];
if(i<j)add(1,0,n,i,j-1,1);
if(i>j)add(1,0,n,j,i-1,-1);
A[i]=inf,change(1,0,n,i);
B[j]=inf,change(1,0,n,j);
}
return printf("%lld",ans),0;
}

  

BZOJ3838 : [Pa2013]Raper的更多相关文章

  1. 题解 洛谷 P4694 【[PA2013]Raper】

    首先考虑题目的性质,不难发现光盘的花费是一个凸函数.当生产 \(0\) 张光盘时,其花费为 \(0\),随着光盘生产数的增加,最优情况肯定是先选择工厂便宜的时刻,所以花费会增长越来越快,因此其为一个下 ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. 【BZOJ3733】[Pa2013]Iloczyn (搜索)

    [BZOJ3733][Pa2013]Iloczyn (搜索) 题面 BZOJ 题解 把约数筛出来之后,直接爆搜,再随便剪枝就过了. 最近一句话题解倾向比较严重 #include<iostream ...

  4. 【BZOJ3837】[Pa2013]Filary 随机化神题

    [BZOJ3837][Pa2013]Filary Description 给定n个正整数,从中挑出k个数,满足:存在某一个m(m>=2),使得这k个数模m的余数相等. 求出k的最大值,并求出此时 ...

  5. 【BZOJ3837】[PA2013]Filary

    [BZOJ3837][PA2013]Filary 题面 darkbzoj 题解 考虑到模数为\(2\)时答案至少为\(\frac n2\),这是我们答案的下界. 那么我们对于任意的一个数,它们答案集合 ...

  6. 【BZOJ】3737: [Pa2013]Euler

    题意: 求满足\(phi(a)=n\)的\(a\)的个数.(\(n \le 10^{10}\)) 分析 这种题一开始就感觉是搜索= = 题解 首先容易得到 \[\phi(n) = \prod_{i} ...

  7. BZOJ 3736: [Pa2013]Karty

    Description 一个0/1矩阵,求能覆盖所有 \(1\) ,同时不覆盖所有 \(0\) 的矩阵,使这个面积最大. Sol DP/悬线法. 首先,所求的矩阵一定可以覆盖所有贴边的悬线. 用悬线法 ...

  8. BZOJ3733 : [Pa2013]Iloczyn

    首先将$n$的约数从小到大排序,设$dfs(x,y,z)$表示当前可以选第$x$个到第$m$个约数,还要选$y$个,之前选的乘积为$z$是否可能. 爆搜的时候,如果从$x$开始最小的$y$个相乘也超过 ...

  9. BZOJ3839 : [Pa2013]Działka

    对于每个询问,首先可以通过扫描线+线段树求出四个方向的第一个点,询问范围等价于框住这些点的最小矩形. 对于一个点$i$,预处理出: $A[i][j]$:$i$往左下角按凸壳走到$j$时,凸壳上相邻两点 ...

随机推荐

  1. storyboard和xib的各种问题

    1.prepareFoSegue注意问题使用该方法设置的值, 必须要 viewWillApear之后用 2.storayboard的使用autolayout, constant = -16, 刚好在f ...

  2. chm文件打开空白无内容的解决办法

    今天下载了个chm文件,但是打开空白,也没显示什么内容,经过一番研究之后终于可以正常显示了,下面把解决办法分享出来供大家参考下,谢谢.   工具/原料 windows7系统 chm文件 方法/步骤   ...

  3. HDU2191多重背包例题

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000 MS Memory Limit: 32768 KB 64-bit integer IO format: %I64d ...

  4. Linux 怎么查看服务的启动进程所占用的目录

    lsof简介 lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以 ...

  5. Ubuntu上如何安装Java,Eclipse,Pydev,Python(自带,不用装),BeautifulSoup

    如何安装Java,如果出于编程的需要安装Java,需要安装的是JDK,而不仅仅是JRE,下面说说如何在Ubuntu下如何安装JDK:只有两步,1.下载并解压,2.配置环境变量1.下载并解压:下载地址: ...

  6. Java RMI 框架

    RMI(即Remote Method Invoke 远程方法调用).在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定 ...

  7. 【leetcode】Palindrome Partitioning II

    Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...

  8. 2.python基础深入(元组、字符串、列表、字典)

    一,对象与类 对象: python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,玩的手机就是对象. 我们通过描述属性(特征)和行为来描述一个对象的. 在python中,一个对象的特 ...

  9. July 19th, Week 30th Tuesday, 2016

    The good seaman is known in bad weather. 惊涛骇浪,方显英雄本色. You can't be afraid to fail. It's the only way ...

  10. CUDA学习笔记(一)——CUDA编程模型

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm56.html CUDA的代码分成两部分,一部分在host(CPU)上运行,是普通的C代码:另一部分在d ...