送礼物 题解

这道题目是到毒瘤题。

首先我们至少去L个,所以我们可以把小于L的用单调队列直接求出。

对取L~R个。显而易见的是左右两端必分别是这个区间的最小值和最大值。我们可以用01分数规划。不放令结果最后为ans,则有:

(a[j]-ans*j)-(a[i]-ans*i)>ans*k

所以我们就可以愉快地分数规划啦。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<deque>
#include<algorithm>

#define maxa 50005
#define me(a) memset(a,0,sizeof(a))

using namespace std;

const double eps=1e-6;
inline void read(int &x){
	x=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c<='9'&&c>='0'){
		x=((x<<1)+(x<<3))+c-'0';
		c=getchar();
	}
	return ;
}
inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c<='9'&&c>='0'){
		x=((x<<1)+(x<<3))+c-'0';
		c=getchar();
	}
	return x;
}
inline void w1(int x){
	if(x){
		w1(x/10);
		putchar(x%10+48);
	}
	return ;
}
inline void write(int x){
	if(x)w1(x);
	else putchar('0');
	return ;
}

int n,k,l,r;
int a[maxa];
double ans=0;
deque <int> q1,q2;//min,max
void Find(){
	for(int i=1;i<=n;i++){
		while(!q1.empty()&&q1.front()<=i-l) q1.pop_front();
		while(!q2.empty()&&q2.front()<=i-l) q2.pop_front();
		
		while(!q1.empty()&&a[q1.back()]>=a[i]) q1.pop_back();
		while(!q2.empty()&&a[q2.back()]<=a[i]) q2.pop_back();
		q1.push_back(i);
		q2.push_back(i);
		ans=max(ans,double(max(a[q2.front()]-a[i],a[i]-a[q1.front()]))/double(l+k-1));
	}
	while(!q1.empty())q1.pop_back();
	while(!q2.empty())q2.pop_back();
	return ;
}
//(a[j]-ans*j)-(a[i]-ans*i)>ans*k
double F(double x){
	double ans=0;
	while(!q1.empty())q1.pop_back();
	while(!q2.empty())q2.pop_back();
	for(int i=1;i<=n;i++){
		double y=a[i]-i*x;
		while(!q1.empty()&&q1.front()<=i-r) q1.pop_front();
		while(!q2.empty()&&q2.front()<=i-r) q2.pop_front();
		
		if(!q1.empty()&&i-q1.front()>=l)ans=max(ans,double(y-(a[q1.front()]-q1.front()*x)-x*k));
		
		while(!q1.empty()&&a[q1.back()]-q1.back()*x>=y) q1.pop_back();
		while(!q2.empty()&&a[q2.back()]-q2.back()*x<=y) q2.pop_back();
		
		q1.push_back(i);
		q2.push_back(i);
		
		
	}
	return ans;
	
}


bool check(double x){
	if(F(x)>eps)return true;
	//for(int i=1;i<=n;i++)cout<<a[i]<<" ";
	for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
	//for(int i=1;i<=n;i++)cout<<a[i]<<" ";
	if(F(x)>eps){
		for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
		return true;
	}
	for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
	return false;
}

void clear(){
	ans=0;
	while(!q1.empty())q1.pop_back();
	while(!q2.empty())q2.pop_back();
	return ;
}
int main(){
	for(int T=read();T--;clear()){
		read(n);read(k);read(l);read(r);
		for(int i=1;i<=n;i++)read(a[i]);
		Find();
		double L=ans,R=1005,mid;
		while(L<R-eps){
			mid=(L+R)/2;
			if(check(mid))L=mid;
			else R=mid;
			//cout<<F(mid)<<" "<<L<<":"<<R<<endl;
		}
		printf("%.4lf\n",mid);
	}
	return 0;
	
}

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<deque>
#include<algorithm>

#define maxa 50005
#define me(a) memset(a,0,sizeof(a))

using namespace std;

const double eps=1e-6;
inline void read(int &x){
    x=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        c=getchar();
    }
    while(c<='9'&&c>='0'){
        x=((x<<1)+(x<<3))+c-'0';
        c=getchar();
    }
    return ;
}
inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        c=getchar();
    }
    while(c<='9'&&c>='0'){
        x=((x<<1)+(x<<3))+c-'0';
        c=getchar();
    }
    return x;
}
inline void w1(int x){
    if(x){
        w1(x/10);
        putchar(x%10+48);
    }
    return ;
}
inline void write(int x){
    if(x)w1(x);
    else putchar('0');
    return ;
}

int n,k,l,r;
int a[maxa];
double ans=0;
deque <int> q1,q2;//min,max
void Find(){
    for(int i=1;i<=n;i++){
        while(!q1.empty()&&q1.front()<=i-l) q1.pop_front();
        while(!q2.empty()&&q2.front()<=i-l) q2.pop_front();
        
        while(!q1.empty()&&a[q1.back()]>=a[i]) q1.pop_back();
        while(!q2.empty()&&a[q2.back()]<=a[i]) q2.pop_back();
        q1.push_back(i);
        q2.push_back(i);
        ans=max(ans,double(max(a[q2.front()]-a[i],a[i]-a[q1.front()]))/double(l+k-1));
    }
    while(!q1.empty())q1.pop_back();
    while(!q2.empty())q2.pop_back();
    return ;
}
//(a[j]-ans*j)-(a[i]-ans*i)>ans*k
double F(double x){
    double ans=0;
    while(!q1.empty())q1.pop_back();
    while(!q2.empty())q2.pop_back();
    for(int i=1;i<=n;i++){
        double y=a[i]-i*x;
        while(!q1.empty()&&q1.front()<=i-r) q1.pop_front();
        while(!q2.empty()&&q2.front()<=i-r) q2.pop_front();
        
        if(!q1.empty()&&i-q1.front()>=l)ans=max(ans,double(y-(a[q1.front()]-q1.front()*x)-x*k));
        
        while(!q1.empty()&&a[q1.back()]-q1.back()*x>=y) q1.pop_back();
        while(!q2.empty()&&a[q2.back()]-q2.back()*x<=y) q2.pop_back();
        
        q1.push_back(i);
        q2.push_back(i);
        
        
    }
    return ans;
    
}


bool check(double x){
    if(F(x)>eps)return true;
    //for(int i=1;i<=n;i++)cout<<a[i]<<" ";
    for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
    //for(int i=1;i<=n;i++)cout<<a[i]<<" ";
    if(F(x)>eps){
        for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
        return true;
    }
    for(int i=1;i<=(n>>1);i++)swap(a[i],a[n-i+1]);
    return false;
}

void clear(){
    ans=0;
    while(!q1.empty())q1.pop_back();
    while(!q2.empty())q2.pop_back();
    return ;
}
int main(){
    for(int T=read();T--;clear()){
        read(n);read(k);read(l);read(r);
        for(int i=1;i<=n;i++)read(a[i]);
        Find();
        double L=ans,R=1005,mid;
        while(L<R-eps){
            mid=(L+R)/2;
            if(check(mid))L=mid;
            else R=mid;
            //cout<<F(mid)<<" "<<L<<":"<<R<<endl;
        }
        printf("%.4lf\n",mid);
    }
    return 0;
    
}

 

posted @ 2019-08-17 16:00  WangQT  阅读(288)  评论(6编辑  收藏  举报