洛谷 1315 观光公交——贪心

题目:https://www.luogu.org/problemnew/show/P1315

要发现对于一个人,其开始时间是给定的,所以让每个人的结束时间尽量早即可!

于是把人挂在其终点上。改一条边可以影响一段点的到站时间,直到有一站在等人为止;影响就是在那些站上挂的人的时间减了1!

于是就有竟然能过的 n*k 做法了。

但真的可以每条边分开考虑吗?毕竟对后面有一些影响。不知贪心正确性。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1005,M=1e4+5;
int n,m,k,d[N],s[N],ari[N],t[N],g[N],mx,ps,T[M],to[M];
ll ans;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
void updt()
{
  for(int i=1;i<=n;i++)
    ari[i]=max(ari[i-1],t[i-1])+d[i];
  int p0=n;mx=-1;
  for(int i=n;i;i--)
    {
      if(ari[i]<=t[i]) p0=i;
      g[i]=p0;
      if(s[p0]-s[i-1]>mx&&d[i])
    {
      mx=s[p0]-s[i-1];
      ps=i;
    }
    }
}
int main()
{
  n=rdn(); m=rdn(); k=rdn(); int tmp=0;
  for(int i=2;i<=n;i++)
    {
      d[i]=rdn(); tmp+=d[i];
    }
  k=min(k,tmp);
  for(int i=1,u;i<=m;i++)
    {
      T[i]=rdn(); u=rdn(); to[i]=rdn();
      t[u]=max(t[u],T[i]); s[to[i]]++;
    }
  for(int i=1;i<=n;i++) s[i]+=s[i-1];
  updt();
  for(int i=1;i<=m;i++)ans+=ari[to[i]]-T[i];
  while(k--)
    {
      ans-=mx; d[ps]--; updt();
    }
  printf("%lld
",ans);
  return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9756981.html