CF 238B Boring Partition

本文解析了CodeForces上的一道B级难度题目,介绍了如何通过将数组分为两部分来最小化godness值的问题,并提供了两种解决方案及其代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/contest/238/problem/B


题目大意:

把一个数组中的数分成两部分

f(ai,aj) = (ai和aj在同一部分)? ai+aj : ai+a[j]+h (i != j)

求最小的godness = max{ f(ai,aj) } - min{ f(ai,aj) }.


题目思路:

我的歪解:

先求出a[]最大值max_a,最小值min_a.

(1)max_a和min_a在一同一部分

(2)max_a和min_a不在同不一部分

在(1)的时候把数组扫一遍,放1时更优就放1,否则放2

同理对(2)也这样处理.

这个证明起来很烦的说。。。

大神的正解:

同样分这两种状况

(1)全在同一部分

(2)min_a单独一部分

先把a[]排序一下,这样a[n]=max_a,a[1]=min_a。

首先我们要知道最小的最大f=a[n]+a[n-1],最大的最小f=a[1]+a[2]+h。

所以最有值是a[n]+a[n-1]-a[1]+a[2]+h,不过这个值不一定能取到。

对于(1)godness=a[n]+a[n-1]-a[1]-a[2]。

对于(2)godness=max(a[n]+a[n-1],a[n]+a[1]+h)-min(a[1]+a[2]+h,a[2]+a[3])。

证明的话相对我的方法比较简单(也挺烦),罗列一下关系,推导。


代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define eps (1e-8)
#define type int
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define MOD 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define _max(x,y) (((x)>(y))? (x):(y))
#define _min(x,y) (((x)<(y))? (x):(y))
#define _abs(x) ((x)<0? (-(x)):(x))
#define getmin(x,y) (x= (x<0 || (y)<x)? (y):x)
#define getmax(x,y) (x= ((y)>x)? (y):x)
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
int TS,cas=1;
const int M=100000+5;
int n,h;
struct node{
    int a,id;
    void read(int i){scanf("%d",&a),id=i;}
    bool operator < (const node &t) const{
        return a < t.a;
    }
}p[M];
int pos[2][M],ans[2];

void run(){
    int i,j;
    for(i=1;i<=n;i++) p[i].read(i);
    if(n<3) puts("0\n1 1");
    else{
        sort(p+1,p+n+1);
        int mmax,mmin;
        int t1,t2,x1,y1,x2,y2;
        int max_in_1,max_in_2,min_in_1,min_in_2;
        pos[0][p[n].id]=2,pos[0][p[1].id]=1;
        min_in_2=p[n].a,max_in_1=p[1].a;
        mmax=mmin=p[n].a+p[1].a+h;
        for(i=2;i<n;i++){
            x1=_max(mmax,p[n].a+p[i].a+h);
            y1=_min(mmin,p[1].a+p[i].a);
            t1=x1-y1;
            x2=_max(mmax,_max(p[n].a+p[i].a,max_in_1+p[i].a+h));
            y2=_min(mmin,_min(min_in_2+p[i].a,p[1].a+p[i].a+h));
            t2=x2-y2;
            if(t1<t2) mmax=x1,mmin=y1,pos[0][p[i].id]=1,getmax(max_in_1,p[i].a);
            else mmax=x2,mmin=y2,pos[0][p[i].id]=2,getmin(min_in_2,p[i].a);
        }
        ans[0]=mmax-mmin;
        
        pos[1][p[n].id]=2,pos[1][p[1].id]=2;
        mmax=mmin=p[n].a+p[1].a;
        min_in_1=INF,max_in_1=-INF;
        for(i=2;i<n;i++){
            x1=_max(mmax,p[n].a+p[i].a+h);
            y1=_min(mmin,_min(min_in_1+p[i].a,p[1].a+p[i].a+h));
            t1=x1-y1;
            x2=_max(mmax,_max(max_in_1+p[i].a+h,p[n].a+p[i].a));
            y2=_min(mmin,p[1].a+p[i].a);
            t2=x2-y2;
            if(t1<t2) mmax=x1,mmin=y1,pos[1][p[i].id]=1,getmin(min_in_1,p[i].a),getmax(max_in_1,p[i].a);
            else mmax=x2,mmin=y2,pos[1][p[i].id]=2;
        }
        ans[1]=mmax-mmin;
        if(ans[0]<ans[1]){
            for(printf("%d\n",ans[0]),i=1;i<=n;i++)
                printf("%d%c",pos[0][i],(i==n)? '\n':' ');
        }else{
            for(printf("%d\n",ans[1]),i=1;i<=n;i++)
                printf("%d%c",pos[1][i],(i==n)? '\n':' ');
        }
    }
}

void preSof(){
}

int main(){
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    preSof();
    //run();
    while(~scanf("%d%d",&n,&h)) run();
    //for(scanf("%d",&TS);cas<=TS;cas++) run();
    return 0;
}

代码(正解):

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define eps (1e-8)
#define type int
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define _max(x,y) (((x)>(y))? (x):(y))
#define _min(x,y) (((x)<(y))? (x):(y))
#define _abs(x) ((x)<0? (-(x)):(x))
#define getmin(x,y) (x= (x<0 || (y)<x)? (y):x)
#define getmax(x,y) (x= ((y)>x)? (y):x)
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
int TS,cas=1;
const int M=100000+5;
int n,h,a[M];

void run(){
    int i,j;
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	if(n==2){puts("0\n1 1");return;}
	j=min_element(a+1,a+n+1)-a;
	sort(a+1,a+n+1);
	int t1=a[n]+a[n-1]-(a[1]+a[2]);
	int t2=_max(a[n]+a[n-1],a[n]+a[1]+h)-_min(a[1]+a[2]+h,a[2]+a[3]);
	if(t1<t2) j=-1;
	printf("%d\n",_min(t1,t2));
	for(i=1;i<=n;i++)
		printf("%d%c",(i==j)? 1:2,(i==n)? '\n':' ');
}

void preSof(){
}

int main(){
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    preSof();
    //run();
    while(~scanf("%d%d",&n,&h)) run();
    //for(scanf("%d",&TS);cas<=TS;cas++) run();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值