網絡流經典題裏餐巾計劃的增強版...天數變成了$10^5$,那就不能用費用流作了...ios
考慮費用流的時候,單位費用隨流量的增長而減小,也就是說費用實際上是個單峯(下凸)函數。網絡
那麼能夠三分要買的餐巾個數,求費用能夠用貪心。ide
新買的沒用就用新買的,不然能慢洗的慢洗,不能慢洗的拿最晚的快洗後能夠當天用的去快洗。函數
有一個錯誤的貪心是慢洗和快洗的都拿最先的,這樣可能會致使快洗的原本能夠洗時間更晚一些的,卻洗了比較早的餐巾,而這些餐巾本能夠在接下來的一天裏經過慢洗來省下更多的錢。spa
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=500010, inf=1e9; struct poi{int tim, rest;}q1[maxn], q2[maxn], q3[maxn]; int d, n1, n2, c1, c2, tc, ans=inf; int t[maxn]; inline void read(int &k) { int f=1; k=0; char c=getchar(); while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar(); while(c<='9' && c>='0') k=k*10+c-'0', c=getchar(); k*=f; } inline int f(int x) { int ans=(tc-c2)*x; int l1, r1, l2, r2, l3, r3; l1=l2=l3=r1=1; r2=r3=0; q1[1].tim=-inf; q1[1].rest=x; for(int i=1;i<=d;i++) { while(l1<=r1 && q1[l1].tim+n1<=i) q2[++r2]=q1[l1++]; while(l2<=r2 && q2[l2].tim+n2<=i) q3[++r3]=q2[l2++]; int rest=t[i]; while(rest) { if(l3<=r3) { if(q3[r3].rest>=rest) q3[r3].rest-=rest, ans+=rest*c2, rest=0; else ans+=q3[r3].rest*c2, rest-=q3[r3--].rest; } else if(l2<=r2) { if(q2[r2].rest>=rest) q2[r2].rest-=rest, ans+=rest*c1, rest=0; else ans+=q2[r2].rest*c1, rest-=q2[r2--].rest; } else return inf; } q1[++r1].tim=i; q1[r1].rest=t[i]; } return ans; } int main() { read(d); read(n1); read(n2); read(c1); read(c2); read(tc); int l=1, r=0; for(int i=1;i<=d;i++) read(t[i]), r+=t[i]; if(n1>n2) swap(n1, n2), swap(c1, c2); if(c1<c2) n2=n1, c2=c1; while(r-l>4) { int mid1=l+(r-l)/3, mid2=l+(r-l)*2/3; if(f(mid1)==inf || f(mid1)>f(mid2)) l=mid1; else r=mid2; } for(int i=l;i<=r;i++) ans=min(ans, f(i)); printf("%d\n", ans); }