题目链接: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;
}