题目背景
这是奇妙的一天,少女 Wu_Mr
的生日。
自然,她的姬友 108oahnew
要来帮她庆生。
空手而来显然不是她的风格,于是她想去帮 Wu_Mr
准备亿些礼物。
就在她在礼品店挑选礼物的时候,一个人把脸贴到了她的耳边。
“这些礼品我都不想要,你陪我睡一晚上,这就是一个相当快乐的生日了。” Wu_Mr
一脸坏笑的说。
108oahnew
呆了一下,回头看着 Wu_Mr
。
“不愿意也可以,做道题吧。”
题面描述
“现在有 n n n 种礼物,每种有两个。对于第 i i i 种礼物,可以不买,也可以花 a i a_i ai 的价格买一个,也可以花 b i b_i bi 的价格买两个。现在我想要 m m m 个礼物,请问最少要花多少价格呢?”
“这……好像有亿点点难,做不出来怎么办?”
“那,你今晚就是我的了哦~” Wu_Mr
好像比真的得到这么多礼物还要开心。
第一行两个整数,表示 n , m n,m n,m 。
接下来 n n n 行,每行两个整数,分别为 a i , b i a_i,b_i ai,bi 。
输出一个数,表示最小的答案。
样例输入
6 8
66 113
81 90
69 107
18 19
50 57
2 146
样例输出
234
对于 10 % 10\% 10% 的数据,保证 n ≤ 10 n \le 10 n≤10
对于 30 % 30\% 30% 的数据,保证 n ≤ 1000 n\le 1000 n≤1000
对于 100 % 100\% 100% 的数据,保证 n ≤ 3 × 1 0 5 , 0 ≤ a i ≤ 1 0 9 , 0 ≤ b i ≤ 1 0 9 , m ≤ 2 n n\le3 \times 10^5,0\le a_i \le 10^9,0 \le b_i \le 10^9,m \le 2n n≤3×105,0≤ai≤109,0≤bi≤109,m≤2n
北京十一 noip2020 模拟
不知为何,考场上无法证明贪心,于是开始最暴力的行为:
模拟费用流(假)。
实际只是模拟退流。但发现无法建出图,于是开始暴力对拍,少啥退啥,多拍就 A C AC AC。(雾)
#include<bits/stdc++.h>
#define N 300005
#define mp make_pair
#define P pair<ll, int>
#define tp top().first
typedef long long ll;
using namespace std;
const ll inf=1e18;
int read(){
int op=1,sum=0;char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
ll a[N],b[N],ans;
priority_queue<pair<ll, int> > q[6];
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
int in[N],cnt[N];
inline void insert(int x,int ca){
in[x]=1;cnt[x]=ca;
if(ca==1){
ans+=a[x];
q[0].push(mp(a[x],x));
q[3].push(mp(-(b[x]-a[x]),x));
}else{
ans+=b[x];
q[1].push(mp(b[x],x));
q[2].push(mp(-(a[x]-b[x]),x));
}
}
inline void cl(int x){
in[x]=0;
if(cnt[x]==1)ans-=a[x];
if(cnt[x]==2)ans-=b[x];
cnt[x]=0;
}
inline void ch(int x){
q[4].push(mp(-a[x],x));
q[5].push(mp(-b[x],x));
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline void cl0(){
while(!q[0].empty()){
int x=q[0].top().second;
if(in[x]==0||(in[x]==1&&cnt[x]==2))q[0].pop();
else return ;
}
}
inline void cl1(){
while(!q[1].empty()){
int x=q[1].top().second;
if(in[x]==0||(in[x]==1&&cnt[x]==1))q[1].pop();
else return ;
}
}
inline void cl2(){
while(!q[2].empty()){
int x=q[2].top().second;
if(in[x]==0||(in[x]==1&&cnt[x]==1))q[2].pop();
else return ;
}
}
inline void cl3(){
while(!q[3].empty()){
int x=q[3].top().second;
if(in[x]==0||(in[x]==1&&cnt[x]==2))q[3].pop();
else return ;
}
}
inline void cl4(){
while(!q[4].empty()){
int x=q[4].top().second;
if(in[x])q[4].pop();
else return ;
}
}
inline void cl5(){
while(!q[5].empty()){
int x=q[5].top().second;
if(in[x])q[5].pop();
else return ;
}
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline ll C1(){
cl2();cl4();
if(q[2].empty()||q[4].empty())return inf;
ll now=-q[2].tp-q[4].tp;
return now;
}
inline ll C2(){
cl0();cl5();
if(q[0].size()<2||q[5].empty())return inf;
P t=q[0].top();ll now=-q[0].tp-q[5].tp;
q[0].pop();cl0();if(q[0].empty()){
q[0].push(t);return inf;}
now-=q[0].tp;q[0].push(t);
return now;
}
inline ll C3(){
cl0();cl4();
if(q[0].empty()||q[4].empty())return inf;
ll now=-q[0].tp-q[4].tp;
return now;
}
inline ll C4(){
cl1();cl5();
if(q[1].empty()||q[5].empty())return inf;
ll now=-q[1].tp-q[5].tp;
return now;
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline ll C5(){
cl1();cl4();
if(q[1].empty()||q[4].empty())return inf;
ll now=-q[1].tp-q[4].tp;P t=q[4].top();q[4].pop();
cl4();if(q[4].empty()){
q[4].push(t);return inf;}
now-=q[4].tp;q[4].push(t);
return now;
}
inline ll C6(){
cl0();cl3();
if(q[0].empty()||q[3].empty())return inf;
ll now=-q[3].tp;int x=q[3].top().second;
if(x==q[0].top().second){
P t=q[0].top();q[0].pop();cl0();
if(q[0].empty()){
q[0].push(t);
return inf;
}
now-=q[0].tp;
q[0].push(t);
}else now-=q[0].tp;
return now;
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline ll C7(){
cl0();cl3();
if(q[0].empty()||q[3].empty())return inf;
ll now=-q[0].tp;int x=q[0].top().second;
if(x==q[3].top().second){
P t=q[3].top();q[3].pop();cl3();
if(q[3].empty()){
q[3].push(t);
return inf;
}
now-=q[3].tp;
q[3].push(t);
}else now-=q[3].tp;
return now;
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline ll C8(){
cl2(),cl3();
if(q[2].empty()||q[3].empty())return inf;
ll now=-q[2].tp-q[3].tp;
return now;
}
inline ll C9(){
cl2();cl0();cl5();
if(q[2].empty()||q[0].empty()||q[5].empty())return inf;
ll now=-q[5].tp-q[0].tp-q[2].tp;
return now;
}
inline ll C10(){
cl2();cl5();
if(q[2].empty()||q[5].empty())return inf;
ll now=-q[2].tp-q[5].tp;
P t=q[2].top();q[2].pop();
cl2();
if(q[2].empty()){
q[2].push(t);
return inf;
}
now-=q[2].tp;q[2].push(t);
return now;
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
inline ll C11(){
cl1();cl4();cl3();
if(q[1].empty()||q[4].empty()||q[3].empty())return inf;
ll now=-q[1].tp-q[4].tp-q[3].tp;
return now;
}
inline ll C12(){
cl1();cl3();
if(q[1].empty()||q[3].empty())return inf;
ll now=-q[1].tp-q[3].tp;
P t=q[3].top();q[3].pop();
cl3();
if(q[3].empty()){
q[3].push(t);
return inf;
}
now-=q[3].tp;
q[3].push(t);
return now;
}
int main(){
int n=read(),m=read();
for(int i=1;i<=n;++i){
a[i]=read(),b[i]=read();
if(m>=2){
insert(i,2);m-=2;
}else{
if(m>=1){
insert(i,1);m--;
}else{
ch(i);
}
}
}
while(1){
ll tmp,now=inf;int pos=0;
if((tmp=C1())<now){
now=tmp,pos=1;
}
if((tmp=C2())<now){
now=tmp,pos=2;
}
if((tmp=C3())<now){
now=tmp,pos=3;
}
if((tmp=C4())<now){
now=tmp,pos=4;
}
if((tmp=C5())<now){
now=tmp,pos=5;
}
if((tmp=C6())<now){
now=tmp,pos=6;
}
if((tmp=C7())<now){
now=tmp,pos=7;
}
if((tmp=C8())<now){
now=tmp,pos=8;
}
if((tmp=C9())<now){
now=tmp,pos=9;
}
if((tmp=C10())<now){
now=tmp;pos=10;
}
if((tmp=C11())<now){
now=tmp;pos=11;
}
if((tmp=C12())<now){
now=tmp;pos=12;
}
if(now>=0)break;
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
if(pos==1){
int x=q[2].top().second,y=q[4].top().second;
cl(x);insert(x,1);insert(y,1);
}
if(pos==2){
int y=q[5].top().second;
for(int i=0;i<=1;++i){
cl0();
int x=q[0].top().second;
cl(x);ch(x);
}
insert(y,2);
}
if(pos==3){
int x=q[0].top().second,y=q[4].top().second;
cl(x);ch(x);insert(y,1);
}
if(pos==4){
int x=q[1].top().second,y=q[5].top().second;
cl(x);ch(x);insert(y,2);
}
if(pos==5){
int x=q[1].top().second,y[2];
for(int i=0;i<=1;++i){
cl4();
y[i]=q[4].top().second;insert(y[i],1);
}
cl(x);ch(x);
}
if(pos==6){
int x=q[3].top().second,y;cl(x);cl0();y=q[0].top().second;
insert(x,2);cl(y);ch(y);
}
if(pos==7){
int x=q[0].top().second,y;//cout<<cnt[x]<<" ";
cl(x);ch(x);cl3();y=q[3].top().second;//cout<<cnt[y]<<endl;
cl(y);insert(y,2);
}
if(pos==8){
int x=q[2].top().second,y=q[3].top().second;
cl(x);insert(x,1);cl(y);insert(y,2);
}
if(pos==9){
int x=q[0].top().second,y=q[2].top().second,z=q[5].top().second;
cl(x);ch(x);cl(y);insert(y,1);insert(z,2);
}
if(pos==10){
int x=q[2].top().second;q[2].pop();cl2();int y=q[2].top().second,z=q[5].top().second;
cl(x);insert(x,1);cl(y);insert(y,1);insert(z,2);
}
if(pos==11){
int x=q[1].top().second,y=q[4].top().second,z=q[3].top().second;
cl(x);ch(x);insert(y,1);cl(z);insert(z,2);
}
if(pos==12){
int x=q[1].top().second,y[2];
for(int i=0;i<=1;++i){
cl3();y[i]=q[3].top().second;
cl(y[i]);insert(y[i],2);
}
cl(x);ch(x);
}
int sum=0;
for(int i=1;i<=n;++i)sum+=cnt[i];
}
printf("%lld\n",ans);
return 0;
}
//0 u1
//1 u2
//2 u2->1
//3 u1->2
//4 d1
//5 d2
实际做法无法证明,只能感性理解:
发现局限在与两种操作权值不同,即一个可以买两个,另一个只能买一个。
于是我们在错误贪心(每次把最小的 a i a_i ai 取出,丢入 b i − a i b_i-a_i bi−ai)的基础上,增加一次性买两个的堆,每次比较一个的堆的前两个和两个的堆的第一个总代价,取最优的。但是为了能取到 m m m,于是一个的堆一次只取一个。
@ 2328995024
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,a[300005],b[300005],ans,bj[300005];
char ls[1005];
struct Node {
ll v,ii;};
priority_queue <Node> q,p;
bool operator < (Node x,Node y) {
return x.v>y.v;}
ll read()
{
ll op=1,sum=0;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
void ot(ll x)
{
if(x==0) {
putchar('0'),putchar('\n');return;}
if(x<0) putchar('-'),x=-x;
int rua=0;
while(x) ls[++rua]=x%10+'0',x/=10;
while(rua) putchar(ls[rua--]);
putchar('\n');
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i) a[i]=read(),b[i]=read(),q.push((Node){
a[i],i}),p.push((Node){
b[i],i});
ll now=0;
while(now<m)
{
Node x=q.top(),y;
while(bj[x.ii]==2)
{
q.pop();
x=q.top();
}
if(now==m-1)
{
ans+=x.v;
++now;
continue;
}
if(p.empty())
{
ans+=x.v;++now;
q.pop();
++bj[x.ii];
if(bj[x.ii]<2) q.push((Node){
b[x.ii]-a[x.ii],x.ii});
continue;
}
q.pop();
if(!q.empty()) y=q.top();
while(bj[y.ii]==2&&(!q.empty()))
{
q.pop();
if(!q.empty()) y=q.top();
}
if(!bj[x.ii])
{
ll rua=b[x.ii]-a[x.ii];
if(q.empty()) y=(Node){
rua,x.ii};
else if(rua<y.v) y=(Node){
rua,x.ii};
}
Node z=p.top();
while(bj[z.ii]&&(!p.empty()))
{
p.pop();
if(!p.empty()) z=p.top();
}
if(p.empty())
{
ans+=x.v;++now;
++bj[x.ii];
if(bj[x.ii]<2) q.push((Node){
b[x.ii]-a[x.ii],x.ii});
continue;
}
if(x.v+y.v<z.v||x.ii==z.ii)
{
++now,ans+=x.v;
++bj[x.ii];
if(bj[x.ii]<2) q.push((Node){
b[x.ii]-a[x.ii],x.ii});
}
else
{
now+=2;ans+=z.v;q.push(x);
bj[z.ii]=2;
}
}
ot(ans);
return 0;
}