標籤:貪心
連結:http://acm.hdu.edu.cn/showproblem.php?pid=4923
題意:,Bi可以是小數。
思路:很機智的想法,對於連續M個1+N個0的一塊來說,最優解一定是,Bi=M/(M+N),因為Bi是遞增的(可以手推),所以如果出現在後面的一塊中的Bi>前面一塊的Bi,那麼就不可能取到最優解,所以將兩塊合并一起處理,這樣過程中就需要用棧來維護了。
代碼:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <map>#include <cstdlib>#include <queue>#include <stack>#include <vector>#include <ctype.h>#include <algorithm>#include <string>#include <set>#define PI acos(-1.0)#define maxn 105#define INF 0x7fffffff#define eps 1e-8typedef long long LL;typedef unsigned long long ULL;using namespace std;int aa[1000005];struct Line{ int t0,t1; double val; void calc() { val=(double)t1/(double)(t1+t0); } double sum() { return val*val*(double)(t0)+(1-val)*(1-val)*(double)(t1); }} l[1000005],h;int main(){ int T; scanf("%d",&T); while(T--) { memset(l,0,sizeof(l)); memset(aa,0,sizeof(aa)); int tot,head=-1,tail=-1; scanf("%d",&tot); for(int i=0; i<tot; i++) scanf("%d",&aa[i]); for(int i=0; i<tot; i++) if(aa[i]==1) { head=i; break; } for(int i=tot-1; i>=0; i--) if(aa[i]==0) { tail=i; break; } if(tail<=head) printf("0.000000\n"); else { int t=head,top=0; while(t<tail) { for(int i=t;i<=tail;i++) if(aa[i]==0) { l[top].t1=i-t; t=i; break; } for(int i=t;i<=tail;i++) { if(i==tail) { l[top].t0=i-t+1; t=i; break; } else if(aa[i]==1) { l[top].t0=i-t; t=i; break; } } l[top].calc(); top++; } stack < Line > st; while(!st.empty()) st.pop(); for(int i=0;i<top;i++) { if(st.empty()) st.push(l[i]); else { while(!st.empty()&&st.top().val>l[i].val) { h=st.top(); st.pop(); l[i].t0+=h.t0; l[i].t1+=h.t1; l[i].calc(); } st.push(l[i]); } } double ans=0; while(!st.empty()) { h=st.top(); ans+=h.sum(); st.pop(); } printf("%.6lf\n",ans); } } return 0;}