题目: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; }