题目
看到这样的题目第一印象是感觉很难,想起背包什么之类的。所以比赛的时候就放弃了。直到看到题解,才发现原来就是贪心。由此看来,确实缺乏深入分析问题的勇气。
设每个锅最小消耗时间是
T
=
m
a
x
{
m
a
x
{
t
i
}
,
⌈
∑
i
=
1
n
t
i
m
⌉
}
T=max\lbrace max \lbrace t_{i} \rbrace, \lceil\frac{\sum_{i=1}^{n} t_{i}}{m}\rceil \rbrace
T=max{max{ti},⌈m∑i=1nti⌉}
令
a
v
g
=
⌈
∑
i
=
1
n
t
i
m
⌉
avg=\lceil\frac{\sum_{i=1}^{n} t_{i}}{m}\rceil
avg=⌈m∑i=1nti⌉
第二次补题:之所以是这样,我们假定每个锅最长煎肉的的时间是
a
v
g
avg
avg,必然会存在
t
i
>
=
a
v
g
t_{i}>=avg
ti>=avg。此时,一个过一定煎不完,所以必须转移到其他锅,其他锅增加
t
i
−
a
v
g
t_{i}-avg
ti−avg。但是此时无法确定的是
(
t
j
+
t
i
−
a
v
g
)
(t_{j}+t_{i}-avg)
(tj+ti−avg)与
a
v
g
avg
avg的大小,因为此时最长为
a
v
g
avg
avg,所以最长时间就是
t
i
t_{i}
ti。所以也就是这个等式的来源。(以上为本菜鸡的想法)
注意,是向上取整(比自己大的最小整数)
#include <bits/stdc++.h>
using namespace std;
#define T int T; scanf("%d", &T); while(T--)
typedef long long ll;
const int maxn=1e5+10;
ll t[maxn];
struct node{
int index, l, r;
};
vector<node> v[maxn];
bool cmp(const node &a, const node &b){
return a.index>b.index;
}
int main()
{
int n, m;
ll temp=0, sum=0;
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++){
scanf("%lld", &t[i]);
temp=max(temp, t[i]);
sum+=t[i];
}
ll res=sum/m;
if(sum%m)
res+=1;
ll time=max(temp, res);
int cnt=1, st=0;
for(int i=0; i<n; i++){
node tmp;
if((st+t[i])<=time){
tmp.index=cnt;
tmp.l=st;
st+=t[i];
tmp.r=st;
v[i].push_back(tmp);
} else {
if(st<time){
tmp.index=cnt;
tmp.l=st;
tmp.r=time;
v[i].push_back(tmp);
}
cnt+=1;
st=(st+t[i])-time;
tmp.index=cnt;
tmp.l=0;
tmp.r=st;
v[i].push_back(tmp);
}
if(st==time){
st=0;
cnt+=1;
}
}
for(int i=0; i<n; i++){
printf("%d", (int)v[i].size());
sort(v[i].begin(), v[i].end(), cmp);
for(int j=0; j<(int)v[i].size(); j++)
printf(" %d %d %d", v[i][j].index, v[i][j].l, v[i][j].r);
printf("\n");
}
return 0;
}