• 送礼物 题解


    这道题目是到毒瘤题。

    首先我们至少去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
    ",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
    ",mid);
        }
        return 0;
        
    }
  • 相关阅读:
    Python 元胞自动机模拟——生命游戏
    ()python画动态图——plt.ion动图使用,训练过程展示
    Python——因子分析(KMO检验和Bartlett's球形检验)
    bind(),unbind(),hover(),toggle(),animate()
    多计算机通信中的时间同步问题
    如何创建自定义尺寸的空白地图
    ROS中的珊格地图——nav_msgs::OccupancyGrid
    c++使用eigen库,矩阵维度错误
    Eigen 求最小二乘
    Mybatis 框架下 SQL 注入攻击的 3 种方式,真是防不胜防!
  • 原文地址:https://www.cnblogs.com/WQT-FFT/p/11368975.html
Copyright © 2020-2023  润新知