hdu 6070 Dirt Ratio

来源:互联网 发布:幼儿园美工室制度 编辑:程序博客网 时间:2024/05/19 15:24

我们先二分答案得到k,那么我们需要在序列中找一段区间使得它的sum/len<=k

转换一下得到sum-len*k<=0

最近有些失了志,不愿去自己动手敲代码。。。。

#include<bits/stdc++.h>  using namespace std;  #define MEM(a,b) memset(a,b,sizeof(a))  #define bug puts("bug");  inline int ll(int k) {return 2*k;}  inline int rr(int k) {return 2*k+1;}  inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}  const int maxn=3e6+10;  struct pr {      double sum,lazy;      int left,right;  }tr[maxn+10];  void pushdown(int k) {      if(tr[k].lazy>1e-9){          tr[ll(k)].sum+=tr[k].lazy;tr[rr(k)].sum+=tr[k].lazy;          tr[ll(k)].lazy+=tr[k].lazy;          tr[rr(k)].lazy+=tr[k].lazy;          tr[k].lazy=0;      }  }  void build(int k,int s,int t,double MI) {      tr[k].left=s;tr[k].right=t;      if(s==t) {tr[k].sum=t*MI;return;}      build(ll(k),s,mid(s,t),MI);      build(rr(k),mid(s,t)+1,t,MI);      tr[k].sum=min(tr[ll(k)].sum,tr[rr(k)].sum);      tr[k].lazy=0;  }  void modify(int k,int s,int t,int x) {      int l=tr[k].left,r=tr[k].right;      if(l==s&&r==t) {          tr[k].lazy+=x,tr[k].sum+=x;          return ;      }      pushdown(k);      int mi=mid(l,r);      if(t<=mi) modify(ll(k),s,t,x);      else if(s>mi) modify(rr(k),s,t,x);      else modify(ll(k),s,mi,x),modify(rr(k),mi+1,t,x);      tr[k].sum=min(tr[ll(k)].sum,tr[rr(k)].sum);  }  double query(int k,int s,int t) {      int l=tr[k].left,r=tr[k].right;      if(l==s&&r==t) return tr[k].sum;      pushdown(k);      int mi=mid(l,r);      double res=1e20;      if (t<=mi) res=query(ll(k),s,t);      else if(s>mi) res=query(rr(k),s,t);      else res=min(query(ll(k),s,mi),query(rr(k),mi+1,t));      return res;  }  int a[700000],last[700000],t,n;  int cal(double x){      build(1,1,n,x);      MEM(last,0);      for(int i=1;i<=n;i++){          modify(1,last[a[i]]+1,i,1);          last[a[i]]=i;          if(query(1,1,i)<=x*(i+1)) return 1;      }      return 0;  }    int main(){      scanf("%d",&t);      while(t--){          scanf("%d",&n);          for(int i=1;i<=n;i++) scanf("%d",&a[i]);          double L=0,R=1.0,mi;          for(int i=0;i<25;i++){              mi=(L+R)/2;              if(cal(mi)) R=mi;              else L=mi;          }          printf("%.8f\n",R);      }      return 0;  }  


原创粉丝点击