E. Yet Another Division Into Teams
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There are nn students at your university. The programming skill of the ii-th student is aiai. As a coach, you want to divide them into teams to prepare them for the upcoming ICPC finals. Just imagine how good this university is if it has 2⋅1052⋅105 students ready for the finals!
Each team should consist of at least three students. Each student should belong to exactly one team. The diversity of a team is the difference between the maximum programming skill of some student that belongs to this team and the minimum programming skill of some student that belongs to this team (in other words, if the team consists of kk students with programming skills a[i1],a[i2],…,a[ik]a[i1],a[i2],…,a[ik], then the diversity of this team is maxj=1ka[ij]−minj=1ka[ij]maxj=1ka[ij]−minj=1ka[ij]).
The total diversity is the sum of diversities of all teams formed.
Your task is to minimize the total diversity of the division of students and find the optimal way to divide the students.
Input
The first line of the input contains one integer nn (3≤n≤2⋅1053≤n≤2⋅105) — the number of students.
The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109), where aiai is the programming skill of the ii-th student.
Output
In the first line print two integers resres and kk — the minimum total diversity of the division of students and the number of teams in your division, correspondingly.
In the second line print nn integers t1,t2,…,tnt1,t2,…,tn (1≤ti≤k1≤ti≤k), where titi is the number of team to which the ii-th student belong.
If there are multiple answers, you can print any. Note that you don't need to minimize the number of teams. Each team should consist of at least three students.
Examples
input
Copy
5
1 1 3 4 2
output
Copy
3 1
1 1 1 1 1
input
Copy
6
1 5 12 13 2 15
output
Copy
7 2
2 2 1 1 2 1
input
Copy
10
1 2 5 129 185 581 1041 1909 1580 8150
output
Copy
7486 3
3 3 3 2 2 2 2 1 1 1
Note
In the first example, there is only one team with skills [1,1,2,3,4][1,1,2,3,4] so the answer is 33. It can be shown that you cannot achieve a better answer.
In the second example, there are two teams with skills [1,2,5][1,2,5] and [12,13,15][12,13,15] so the answer is 4+3=74+3=7.
In the third example, there are three teams with skills [1,2,5][1,2,5], [129,185,581,1041][129,185,581,1041] and [1580,1909,8150][1580,1909,8150] so the answer is 4+912+6570=74864+912+6570=7486.
分析:显然同一组的人一定是排序后连续的一堆人。那么排序后dp一下就可以了。
dp[i]表示前i的最小答案,转移分两种情况
(1)直接加入i-1这个人的组,dp[i]=dp[i-1]+a[i]-a[i-1]
(2)从新开一个组,那么从4到i-2遍历,dp[i]=min(dp[j-1]+a[i]-a[j])
对于第一种状态直接转移,第二种状态记录一个最小值就可以O(1)转移了。然后再记录一下dp路径来分组就可以了。
#include <bits/stdc++.h>
using namespace std;
pair<int, int> a[200004];
int dp[200004];
int tp[200004];
int ans[200004];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i].first);
a[i].second = i;
}
sort(a + 1, a + 1 + n);
dp[3] = a[3].first - a[1].first;
tp[3] = 1;
int mini = 1e9;
int cnt = -1;
for (int i = 4; i <= n; ++i) {
if (i - 2 >= 4) {
if (mini > dp[i - 3] - a[i - 2].first) {
cnt = i - 2;
mini = dp[i - 3] - a[i - 2].first;
}
}
dp[i] = dp[i - 1] + a[i].first - a[i - 1].first;
tp[i] = tp[i - 1];
if (mini + a[i].first < dp[i]) {
dp[i] = mini + a[i].first;
tp[i] = cnt;
}
}
int pos = 1;
int nex = tp[n];
for (int i = n; i >= 1; --i) {
ans[a[i].second] = pos;
if (i == nex) {
pos++;
nex = tp[i - 1];
}
}
cout << dp[n] << ' ' << pos - 1 << endl;
for (int i = 1; i <= n; ++i) {
printf("%d ", ans[i]);
}
}