[CSP-S模拟测试]:C(三分+贪心)

Posted wzc521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CSP-S模拟测试]:C(三分+贪心)相关的知识,希望对你有一定的参考价值。

题目传送门(内部题46)


输入格式

第一行$3$个整数$n,m,t$。
第二行$n$个整数,表示$P_i$。
接下来$m$行每行两个整数,表示$L_i,R_i$。


输出格式

一行一个整数表示答案。


样例

样例输入:

3 3 2
6 2 5
1 1
2 2
3 3

样例输出:

11


数据范围与提示

样例解释:

最优方案为使用$2$次特殊加热器,$4$次$1$号加热器,$3$次$3$号加热器。

数据范围:

对于前$20\\%$的数据:$t\\geqslant n$
对于另$30\\%$的数据:$P_i\\leqslant 30$
对于所有数据:
$1\\leqslant n,m,t\\leqslant 10^5$
$1\\leqslant L_i,R_i\\leqslant n$
$1\\leqslant P_i\\leqslant 10^7$


题解

首先,如果你不傻,特殊加热器肯定是在一开始使用。

然而随着我们使用次数的增加,普通加热器所减少的费用也越来越小,所以这是一个上凸函数,所以我们考虑三分使用次数。

剩下的贪心即可。

时间复杂度:$\\Theta(n\\log_1.5(\\max(P_i)))$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct recint L,R;e[100001];
int n,m;
long long t;
int P[100001];
int cnt[100001];
long long ans=1LL<<60;
int h[100001],tag[100001];
long long judge(int x)

	for(int i=1;i<=n;i++)h[i]=max(0,P[i]-x);
	long long res=x*t;
	int flag=0;
	for(int i=1;i<=n;i++)
	
		flag-=tag[i];
		tag[i]=0;
		h[i]=max(0,h[i]-flag);
		res+=h[i];
		flag+=h[i];
		tag[cnt[i]+1]+=h[i];
	
	return res;

int main()

	scanf("%d%d%lld",&n,&m,&t);
	for(int i=1;i<=n;i++)cnt[i]=-1;
	for(int i=1;i<=n;i++)scanf("%d",&P[i]);
	for(int i=1;i<=m;i++)
	
		scanf("%d%d",&e[i].L,&e[i].R);
		cnt[e[i].L]=max(cnt[e[i].L],e[i].R);
	
	int lft=0,rht=0;
	for(int i=1;i<=n;i++)
	
		if(cnt[i-1]>=i)
		
			rht=max(rht,cnt[i]);
			cnt[i]=rht;
		
		if(cnt[i]==-1)lft=max(lft,P[i]);
	
	rht=10000000;
	while(lft<=rht)
	
		int mid=(lft+rht)>>1;
		long long flagl=judge(mid),flagr=judge(mid+1);
		if(flagl>=flagr)
		
			lft=mid+1;
			ans=min(ans,flagr);
		
		else
		
			rht=mid-1;
			ans=min(ans,flagl);
		
	
	printf("%lld",ans);
	return 0;


rp++

以上是关于[CSP-S模拟测试]:C(三分+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

[CSP-S模拟测试]:爬(贪心)

[CSP-S模拟测试]:简单的填数(贪心+模拟)

0929CSP-S模拟测试赛后总结

[CSP-S模拟测试]:Tree(贪心)

[CSP-S模拟测试]:d(贪心+树状数组)

[CSP-S模拟测试]:Emotional Flutter(贪心)