题意:有n个学习领域,每个领域有m个课程,学习第i个领域的第j个课程可以获得sij个技能点,在每个领域中选择一个课程,要求获得的n个技能点的最大值减最小值最小,输出符合要求的策略。
解法:尺取法。将课程的技能点按值进行排序,同时要记录每个值对应的领域,用尺取法选择第一段包含全部领域的区间,区间的边界即为最值,然后将左指针逐步右移,直到出现有的领域没有选课,继续右移右指针,直到结束。当右指针已移到最右的时候需要特判,只移动左指针。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
int c[205];
struct node
{
int a, b, c;
bool operator < (const node &tmp) const
{
if(a == tmp.a)
return b < tmp.b;
return a < tmp.a;
}
bool operator == (const node &tmp) const
{
return a == tmp.a && b == tmp.b;
}
node(int a, int b, int c) : a(a), b(b), c(c){}
node() {}
};
vector <node> v;
int n;
bool judge(int cnt[])
{
for(int i = 0; i < n; i++)
if(!cnt[i])
return false;
return true;
}
int main()
{
while(~scanf("%d", &n))
{
v.clear();
for(int i = 0; i < n; i++)
{
scanf("%d", &c[i]);
}
if(n == 1 && c[0] == 1) //需要特判否则RE
{
int x;
scanf("%d", &x);
printf("0\n1\n");
continue;
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < c[i]; j++)
{
int s;
scanf("%d", &s);
v.push_back(node(s, i, j + 1));
}
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int len = v.size();
int flag = 0;
int now = -1;
int cnt[205] = {0};
int l = 0, r = 0;
cnt[v[0].b] = 1;
int ans = INT_MAX, pl, pr;
for(; l < len;)
{
if(!flag)
{
r++;
cnt[v[r].b]++;
if(judge(cnt))
{
flag = 1;
if(v[r].a - v[l].a < ans)
{
ans = v[r].a - v[l].a;
pl = l, pr = r;
}
continue;
}
}
else
{
if(~now && r < len - 1)
{
r++;
cnt[v[r].b]++;
if(cnt[now])
{
now = -1;
if(v[r].a - v[l].a < ans)
{
ans = v[r].a - v[l].a;
pl = l, pr = r;
}
}
}
else
{
if(r == len - 1)
{
cnt[v[l].b]--;
l++;
if(judge(cnt))
{
if(v[r].a - v[l].a < ans)
{
ans = v[r].a - v[l].a;
pl = l, pr = r;
}
}
continue;
}
cnt[v[l].b]--;
if(!cnt[v[l].b])
{
now = v[l].b;
l++;
}
else
{
l++;
if(v[r].a - v[l].a < ans)
{
ans = v[r].a - v[l].a;
pl = l, pr = r;
}
}
}
}
}
printf("%d\n", ans);
int prt[205];
for(int i = pl; i <= pr; i++)
{
prt[v[i].b] = v[i].c;
}
for(int i = 0; i < n; i++)
{
if(i)
printf(" ");
printf("%d", prt[i]);
}
puts("");
}
return 0;
}