文章目录
- 题目
- 思路
- 代码
- 思考
题目
Luogu
1≤n≤1,000,1≤m≤10,000,0≤k≤100,000,0≤Di?≤1000,0≤Ti≤100,0001≤n≤1,000,1≤m≤10,000,0≤k≤100,000,0≤D_i?≤1000,0≤T_i≤100,0001≤n≤1,000,1≤m≤10,000,0≤k≤100,000,0≤Di??≤1000,0≤Ti?≤100,000
思路
首先思考,问什么可以贪心?
据说当初考试时,很多人想的 DpDpDp 然后就挂了
这也是出题人和考生玩心理战术
为了更好说明为什么可以贪心,我们记
fif_ifi? 为不使用氮气加速到达 iii 点时间,
cnticnt_icnti? 为 iii 点下车人数,
LastiLast_iLasti?在 iii 点最晚出发时间
则 fi=max{fi?1,Lsti?1}+di?1f_i=max\{f_{i-1},Lst_{i-1}\}+d_{i-1}fi?=max{
fi?1?,Lsti?1?}+di?1?
对发现我们只对 fif_ifi?,LastiLast_iLasti? 的大小关系会影响我们决策
也就是人等车和车等人两种
我们可以进行分类讨论
1.fi>Lastif_i>Last_ifi?>Lasti?(人等车)
由于它加速后也会影响到后一段,所以可以暴力找出在它后面连续的一段 fj>Lastjf_j>Last_jfj?>Lastj?
在这些位置下车的人都会提前 111 单位时间下车
2.fi<=Lastif_i<=Last_ifi?<=Lasti?(车等人)
此时并不会对 iii 后面的产生影响,只会影响这 cnticnt_icnti? 个人
综上我们每次只需要这样一段就行了:
影响的人数是这一段下车人数之和
问题来了,为什么可以贪心?
口胡一下(因为贪心本身就不好说)
因为每一段有 DiD_iDi? 的限制
假设现在你就取包含这一段最大的区间 DiD_iDi? 又恰好是最小的
你早取晚取都会把 DiD_iDi? 取完,然后就裂成了两段
假设不取 DiD_iDi? 没有取 DiD_iDi? 优
每次取最大的影响人数
觉得应该可以从 DpDpDp 决策最优来讲,但是懒,不会
代码
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#include<ctime>
#include<bitset>
#include<cmath>
#include<cstdio>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
int read(){
bool f=0;int x=0;char c=getchar();while(c<'0'||'9'<c){
if(c=='-')f=1;c=getchar();}while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();return !f?x:-x;
}
#define MAXN 100000
#define INF 0x3f3f3f3f
int d[MAXN+5],Last[MAXN+5],cnt[MAXN+5],f[MAXN+5];
int Max(int a,int b){
return a>b?a:b;}
int T[MAXN+5],A[MAXN+5],B[MAXN+5];
int main(){
//f[i]:到达 i 实际时间 int n=read(),m=read(),k=read();for(int i=1;i<n;i++)d[i]=read();for(int i=1;i<=m;i++){
T[i]=read(),A[i]=read(),B[i]=read();Last[A[i]]=Max(Last[A[i]],T[i]);cnt[B[i]]++;}f[1]=0;for(int i=2;i<=n;i++)f[i]=Max(f[i-1],Last[i-1])+d[i-1];while(k--){
int Maxnum=0,L=0,R=0;for(int i=2;i<=n;i++){
if(d[i-1]==0) continue;int tmp=0,p1=i,p2=n;for(int j=i;j<=n;j++){
tmp+=cnt[j];if(f[j]<=Last[j]){
p2=j;break;}}if(tmp>Maxnum)Maxnum=tmp,L=p1,R=p2;}if(!Maxnum) break;d[L-1]--;for(int i=L;i<=R;i++)f[i]--;}int ans=0;for(int i=1;i<=m;i++)ans+=f[B[i]]-T[i];printf("%d\n",ans);return 0;
}
思考
多积累对贪心题的认知