Yet Another Division Into Teams
E. Yet Another Division Into Teams
首先要想明白一个东西,就是当一个小组达到六个人的时候,它一定可以拆分成两个更优的小组。
这个题可以用动态规划来写,用一个数组来保存状态,用一个队列来尝试新的状态,但是因为上面的这个特性,每一次只会有三个新的状态。
我们用
sum
来保存躲避选择的元素,举个例子:分组情况为:1 2 3 | 5 6 8 11 | 20 21 22 (不一定满足题意,只是为了说明
sum
的意义)则
sum=(5-3)+(20-11)=11
那么这样分组的总代价为:
a[n]-a[1]-sum=22-1-11
那么我们的目的就是使
sum
尽可能的大,这样分组的代价才会尽可能的小。另外还需要注意一点,就是三人才能成一组,所以就需要三个变量来进行一个轮回,来保证至少三人一组。
for(int i=4;i<=n;++i) { pre[i]=sum.se; pii temp={sum.fi+a[i].fi-a[i-1].fi, i}; sum=max(sum,t1); t1=t2,t2=temp; }
代码:
// Created by CAD on 2019/11/6.
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<long long,int>
using namespace std;
const int maxn=2e5+5;
pii a[maxn];
int pre[maxn];
int out[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n; cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i].fi,a[i].se=i;
sort(a+1,a+n+1);
pii sum={0,0},t1={0,0},t2={0,0};
for(int i=4;i<=n;++i)
{
pre[i]=sum.se;
pii temp={sum.fi+a[i].fi-a[i-1].fi, i};
sum=max(sum,t1);
t1=t2,t2=temp;
}
cout<<a[n].fi-a[1].fi-sum.fi<<" ";
int i=sum.se;
int v=n,cnt=0;
while(v>0)
{
int u=i;
cnt++;
for(;u<=v;u++)
out[a[u].se]=cnt;
v=i-1,i=pre[i];
}
cout<<cnt<<endl;
for(i=1;i<n;++i)
cout<<out[i]<<" ";
cout<<out[n]<<endl;
return 0;
}