洛谷P4644 [USACO2005 Dec]Cleaning Shifts 清理牛棚 [DP,數據結構優化]
題目傳送門
清理牛棚
題目描述
Farmer John‘s cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer John, the most obliging of farmers, has no choice but hire some of the cows to clean the barn. Farmer John has N (1 <= N <= 10,000) cows who are willing to do some cleaning. Because dust falls continuously, the cows require that the farm be continuously cleaned during the workday, which runs from second number M to second number E during the day (0 <= M <= E <= 86,399). Note that the total number of seconds during which cleaning is to take place is E-M+1. During any given second M..E, at least one cow must be cleaning. Each cow has submitted a job application indicating her willingness to work during a certain interval T1..T2 (where M <= T1 <= T2 <= E) for a certain salary of S (where 0 <= S <= 500,000). Note that a cow who indicated the interval 10..20 would work for 11 seconds, not 10. Farmer John must either accept or reject each individual application; he may NOT ask a cow to work only a fraction of the time it indicated and receive a corresponding fraction of the salary. Find a schedule in which every second of the workday is covered by at least one cow and which minimizes the total salary that goes to the cows.
約翰的奶牛們從小嬌生慣養,她們無法容忍牛棚裏的任何臟東西.約翰發現,如果要使這群有潔癖的奶牛滿意,他不得不雇傭她們中的一些來清掃牛棚, 約翰的奶牛中有N(1≤N≤10000)頭願意通過清掃牛棚來掙一些零花錢.由於在某個時段中奶牛們會在牛棚裏隨時隨地地亂扔垃圾,自然地,她們要求在這段時間裏,無論什麽時候至少要有一頭奶牛正在打掃.需要打掃的時段從某一天的第M秒開始,到第E秒結束f0≤M≤E≤86399).註意這裏的秒是指時間段而不是時間點,也就是說,每天需要打掃的總時間是E-M+I秒. 約翰已經從每頭牛那裏得到了她們願意接受的工作計劃:對於某一頭牛,她每天都願意在笫Ti,.T2秒的時間段內工作(M≤Ti≤馬≤E),所要求的報酬是S美元(0≤S≤500000).與需打掃時段的描述一樣,如果一頭奶牛願意工作的時段是每天的第10_20秒,那她總共工作的時間是11秒,而不是10秒.約翰一旦決定雇傭某一頭奶牛,就必須付給她全額的工資,而不能只讓她工作一段時間,然後再按這段時間在她願意工作的總時間中所占的百分比來決定她的工資.現在請你幫約翰決定該雇傭哪些奶牛以保持牛棚的清潔,當然,在能讓奶牛們滿意的前提下,約翰希望使總花費盡量小.
輸入輸出格式
輸入格式:
- Line 1: Three space-separated integers: N, M, and E. * Lines 2..N+1: Line i+1 describes cow i‘s schedule with three space-separated integers: T1, T2, and S.
第1行:3個正整數N,M,E,用空格隔開.
第2到N+1行:第i+l行給出了編號為i的奶牛的工作計劃,即3個用空格隔開的正整數Ti,T2,S.
輸出格式:
- Line 1: a single integer that is either the minimum total salary to get the barn cleaned or else -1 if it is impossible to clean the barn.
輸出一個整數,表示約翰需要為牛棚清理工作支付的最少費用.如果清理工作不可能完成,那麽輸出-1.
輸入輸出樣例
輸入樣例#1:3 0 4
0 2 3
3 4 2
0 0 1
輸出樣例#1: 5
說明
約翰有3頭牛,牛棚在第0秒到第4秒之間需要打掃.第1頭牛想要在第0,1,2秒內工作,為此她要求的報酬是3美元.其余的依此類推. 約翰雇傭前兩頭牛清掃牛棚,可以只花5美元就完成一整天的清掃.
分析:
數據結構優化$DP$的模板。
不難想到暴力的轉移方程,令$L,R$為總的區間,$l,r$為每一頭牛清理的區間。先把每個區間按照右端點從小到大排序,然後轉移方程就是$dp[r]=min(dp[r],min\{dp[l-1],dp[l],...dp[r]\}+s[i])$。但是直接暴力轉移的話復雜度是$O(n^2)$的,不過我們明顯可以發現,中間對$dp[l-1]$到$dp[r]$取$min$的過程是$RMQ$,所以可以套個線段樹求解,這樣就可以$A$了,不過數據比較卡,註意邊界問題。
Code:
//It is made by HolseLee on 24th Sep 2018 //Luogu.org P4644 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+7; int n,L,R; int seg[N<<2],dp[N]; struct Node { int l,r,s; }a[N]; inline int read() { char ch=getchar(); int num=0; bool flag=false; while( ch<‘0‘ || ch>‘9‘ ) { if( ch==‘-‘ ) flag=true; ch=getchar(); } while( ch>=‘0‘ && ch<=‘9‘ ) { num=num*10+ch-‘0‘; ch=getchar(); } return flag ? -num : num; } inline void pushup(int rt) { seg[rt]=min(seg[rt<<1],seg[rt<<1|1]); } void build(int l,int r,int rt) { if( l>r ) return; if( l==r ) { seg[rt]=dp[l]; return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } int quary(int l,int r,int rt,int LL,int RR) { int ret=1<<30; if( r<LL || l>RR ) return ret; if( LL<=l && r<=RR ) return seg[rt]; int mid=(l+r)>>1; if( LL<=mid ) ret=min(ret,quary(l,mid,rt<<1,LL,RR)); if( RR>mid ) ret=min(ret,quary(mid+1,r,rt<<1|1,LL,RR)); return ret; } void update(int l,int r,int rt,int pos,int x) { if( l>pos || r<pos ) return; if( l==r && l==pos ) { seg[rt]=x; return; } int mid=(l+r)>>1; if( pos<=mid ) update(l,mid,rt<<1,pos,x); else update(mid+1,r,rt<<1|1,pos,x); pushup(rt); } inline bool cmp(Node x,Node y) { return x.r<y.r; } int main() { n=read(); L=read(); R=read(); for(int i=1; i<=n; ++i) { a[i].l=read(), a[i].r=read(), a[i].s=read(); } sort(a+1,a+n+1,cmp); memset(dp,0x3f,sizeof(dp)); dp[L]=0; build(L,R,1); for(int i=1; i<=n; ++i) { dp[a[i].r]=min(dp[a[i].r],quary(L,R,1,a[i].l-1,a[i].r)+a[i].s); update(L,R,1,a[i].r,dp[a[i].r]); if( a[i].r>=R ) { if( dp[a[i].r]==0x3f3f3f3f ) printf("-1"); else printf("%d\n",dp[a[i].r]); break; } } return 0; }
洛谷P4644 [USACO2005 Dec]Cleaning Shifts 清理牛棚 [DP,數據結構優化]