[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(三分+贪心)的主要内容,如果未能解决你的问题,请参考以下文章