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\n",max(ans,l));
  }
  return 0;
}

 

posted @ 2017-03-07 16:59  liu_runda  阅读(647)  评论(0编辑  收藏  举报
偶然想到可以用这样的字体藏一点想说的话,可是并没有什么想说的. 现在有了:文化课好难