P1315 观光公交 |
贪心
题目链接:https://www.luogu.org/problemnew/show/1315
哇,这个题贪心?好高级的贪心……完全没看出来QAQ
看到这个题,
刚开始想能不能dp,
然后某大神说不满足无后效性,
首先对于每个点当然是能走就走,
不能走就等待,这是无法控制的。
所以只考虑氮气加速器加在哪里可以使时间总和尽量少。
后效性:
如果选择加速,可能会使后面等待的时间更长,或者更短,对后面都会有影响。
虽然dp不行,但是可以受启发,着这一条边加速会影响后面的所有边么?
不一定。
来来来,分类讨论。
①到下一个点还需要等待:以后的时间就不再影响了 |
②到下一个点不需要等待:对以后的时间还会加速直到……出现情况一(或者到最后一个点)!! |
即每次用加速器都会对后面的人有影响,
用sum[i]记录到i的人数,前缀和处理,g[i]代表每个点所能影响到的最远点,
那么sum[i + g[i]] - sum[i] 即是能影响到的人数
这样就很容易想到选择影响尽量大的点减掉,(这里贪心)
定义数组 :
last[ i ] : 最后一个人到达i站点的时间。
sum[ i ] : 到i站点的总人数。
enter[ i ] : 公交车到i站点的最少时间(用last和enter来更新g,想想怎么更新)。
g[ i ] : 每个站点所能影响到的最远站点,即要求的影响。
Codes:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int N = 20000 + 10; int n,m,k; int dis[N],last[N],g[N],enter[N]; int ans,sum[N],maxx = -1; struct node{ int time,start,end; }a[N]; void init(){ for(int i = 1;i <= m;++ i){ last[a[i].start] = max(last[a[i].start],a[i].time);//最后一个人到a[i].start站点的时间 //和到这个点的时间取max sum[a[i].end] ++; } enter[1] = last[1]; for(int i = 1;i <= n;++ i){ sum[i] += sum[i - 1];//到i站点的总人数 前缀和处理 } for(int i = 2;i <= n;++ i){ enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//公车到i站点的最少时间 //和最后到的时间取max } for(int i = 1;i <= m;++ i) ans += enter[a[i].end] - a[i].time;//处理出不加加速器的answer,后面就可以直接减啦~ return; } void work(int k){ for(;k;-- k){ g[n] = g[n - 1] = n; int tar; maxx = -1; for(int i = n - 2;i >= 1;-- i){ if(enter[i + 1] <= last[i + 1])//下一个点如果等待 g[i] = i + 1;//最多影响到下一个 else //不等待 g[i] = g[i + 1];//继续减少后面的时间 } for(int i = 1;i < n;++ i){//for边数 int tmp = sum[g[i]] - sum[i];//最多影响的人数 if(tmp > maxx && dis[i] > 0){ maxx = tmp; tar = i;//标记最优情况减的点 } } ans -= maxx;//更新ans dis[tar] --;//减掉dis for(int i = 2;i <= n;++ i){ enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//重新更新enter } } return; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i = 1;i < n;++ i){ scanf("%d",&dis[i]); } for(int i = 1;i <= m;++ i){ scanf("%d%d%d",&a[i].time,&a[i].start,&a[i].end); } init(); work(k); cout << ans << ‘\n‘; return 0; }
MAS:
贪心真的是智商题QAQ,还是要多练吧。
时间: 2024-10-06 23:14:00