• bzoj4476[JSOI2015]送礼物


    选择一段区间之后,对答案有影响的只是区间中的最大最小值,因此考虑枚举最大值找最优的最小值.(不需要保证这两个数值是对应的区间内的实际最大最小值,实际最大最小值对答案产生的贡献一定也会另外被枚举到).

    由对称性,只考虑最小值在最大值左边的情况.对于下标等于x的数,如果让下标在[x-l+1,x-1]内的数字作为对应的最小值,那么必然需要延伸这个区间使得区间长度达到l.那么对于这种情况,我们查询这个下标范围内的最小数值即可(每个数值对应的区间长度相同).如果让下标和x的差值大于l小于r的数字作为最小值,则不同的数值对应不同的区间长度,且贪心可得对应的区间一定是一端为最大值,一段为最小值.分数规划,二分答案+单调队列判定即可.二分精度要高一点才不会WA….

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=50005;
    int a[maxn],st[maxn][20];
    int buf[maxn];
    int n,k,l,r;
    int rmq(int l,int r){
      if(l>n||r<1)return 0x7f7f7f7f;
      if(l<1)l=1;
      if(r>n)r=n;
      int j=buf[r-l+1];
      return min(st[l][j],st[r-(1<<j)+1][j]);
    }
    int q[maxn];
    bool check(double ans){
      int head=0,tail=0;
      for(int i=1;i<=n-l;++i){
        while(head!=tail&&i+l>q[head]+r-1)head++;
        while(head!=tail&&(a[q[tail-1]]-q[tail-1]*ans)>(a[i]-i*ans))tail--;
        q[tail++]=i;
        if(a[i+l]-(i+l+k)*ans>a[q[head]]-q[head]*ans)return true;
      }
      head=0;tail=0;
      for(int i=n;i>l;--i){
        while(head!=tail&&i-l<q[head]-r+1)head++;
        while(head!=tail&&(a[q[tail-1]]+(q[tail-1]+k)*ans>a[i]+(i+k)*ans))tail--;
        q[tail++]=i;
        if(a[i-l]+(i-l)*ans>a[q[head]]+(q[head]+k)*ans)return true;
      }
      return false;
    }
    int main(){
      int tests;scanf("%d",&tests);
      for(int j=0;(1<<j)<maxn;++j)buf[1<<j]=j;
      for(int i=3;i<maxn;++i){
        if(!buf[i])buf[i]=buf[i-1];
      }
      while(tests--){
        scanf("%d%d%d%d",&n,&k,&l,&r);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)st[i][0]=a[i];
        for(int j=1;(1<<j)<=n;++j){
          for(int i=1;i<=n;++i){
        st[i][j]=st[i][j-1];
        if(i+(1<<j-1)<=n&&st[i+(1<<j-1)][j-1]<st[i][j])st[i][j]=st[i+(1<<j-1)][j-1];
          }
        }
        double ans=0;
        for(int i=1;i<=n;++i){
          ans=max(ans,(a[i]-min(rmq(i+1,i+l-1),rmq(i-l+1,i-1)))/double(l-1+k));
        }
        double l=0,r=1e4;
        while(r-l>1e-7){
          double mid=(l+r)/2.0;
          if(check(mid))l=mid;
          else r=mid;
        }
        printf("%.4f
    ",max(ans,l));
      }
      return 0;
    }
  • 相关阅读:
    收藏的网站
    记录
    在我的收藏列表里取消收藏功能的实现(不使用直接操作dom的方法)
    uniapp预览图片
    uni-app 中如何打开外部应用,如:浏览器、淘宝、AppStore、QQ等
    uniapp打包上架ios
    uniapp实现倒计时
    uniapp实现支付功能
    uniapp关闭页面回弹效果
    uniapp中使用websocket实现实时聊天功能
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6515654.html
Copyright © 2020-2023  润新知