DTOJ#5238. 庆生会

传送门

题目背景

这是奇妙的一天,少女 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 n10

对于 30 % 30\% 30% 的数据,保证 n ≤ 1000 n\le 1000 n1000

对于 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 n3×105,0ai109,0bi109,m2n

北京十一 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 biai)的基础上,增加一次性买两个的堆,每次比较一个的堆的前两个和两个的堆的第一个总代价,取最优的。但是为了能取到 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;
} 

猜你喜欢

转载自blog.csdn.net/CSDNzhanghongyu/article/details/110500953