1. 程式人生 > >HDU 6070 Dirt Ratio

HDU 6070 Dirt Ratio

一個 i+1 區間 數組實現 build tac urn can memset

隊友已經寫過一個代碼了,用數組實現的線段樹,自己再寫了一個結構體的線段樹,嗯,就是這樣,線段樹風格不一樣而已。

題解:滿足的關系:res=size(l--->r) / (r-l+1) ,求得最小的結果。正面解題,因為不知道res,而這樣做的枚舉每一個區間會得到n2的復雜度,所以枚舉每一個可能的答案,然後再找是否存在可以滿足的這樣解的區間,如果不存在,那就根據枚舉的mid和siza(l--->r) /(r-l+1)的關系更改mid的值。這道題目是滿足單調性的,所以可以二分答案去做。

參考代碼:

#include <stdio.h>
#include <algorithm>
#include 
<math.h> #include <string.h> #include <vector> #include <queue> #include <stack> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int maxn=100010; struct node { int l,r; double sum,lazy; void update(double x) { sum+=x; lazy
+=x; } }tree[maxn*4]; void push_up(int x) { tree[x].sum=min(tree[x<<1].sum,tree[x<<1|1].sum); } void push_down(int x) { double lazyval=tree[x].lazy; if(lazyval>1e-9) { tree[x<<1].update(lazyval); tree[x<<1|1].update(lazyval); tree[x].lazy
=0; } } void build(int x,int l,int r,double Mid) { tree[x].l=l,tree[x].r=r;//,tree[x].sum=0; if(r==l) tree[x].sum=Mid*l; else { int mid=(l+r)>>1; build(x<<1,l,mid,Mid); build(x<<1|1,mid+1,r,Mid); tree[x].lazy=0; push_up(x); } } void update(int x,int ql,int qr,double val) { int L=tree[x].l,R=tree[x].r; if(ql<=L&&R<=qr) tree[x].update(val); else { push_down(x); int mid=(L+R)>>1; if(mid>=ql) update(x<<1,ql,qr,val); if(qr>mid) update(x<<1|1,ql,qr,val); push_up(x); } } double query(int x,int ql,int qr) { int L=tree[x].l,R=tree[x].r; if(ql<=L&&R<=qr) return tree[x].sum; else { push_down(x); double ans=1e20; int mid=(L+R)>>1; if(mid>=ql) ans=min(ans,query(x<<1,ql,qr)); if(qr>mid) ans=min(ans,query(x<<1|1,ql,qr)); //push_up(x); return ans; } } int n,a[maxn],last[maxn]; int fun(double mid) { build(1,1,n,mid); memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { update(1,last[a[i]]+1,i,1); last[a[i]]=i; //printf("%lf %lf\n",query(1,1,i),mid*(i+1)); if(query(1,1,i)<=(double)mid*(i+1)) return 1; } return 0; } int main() { //freopen("C:\\Users\\Administrator\\Desktop\\a.txt","r",stdin); //freopen("C:\\Users\\Administrator\\Desktop\\b.txt","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); double mid=0.0,l=0.0,r=1.0,ans=0.0; for(int i=0;i<20;i++) { mid=(l+r)/2; if(fun(mid)) r=mid,ans=mid; else l=mid; } printf("%.10lf\n",ans); } return 0; }

  

HDU 6070 Dirt Ratio