题意:
给定
n
n
n天,每天生产
k
i
k_i
ki件衣服,选择
m
m
m件来自不同天的衣服,求最大价格和最小价格的最小差值。
数据范围:
1
≤
n
≤
1
0
6
,
1
≤
m
≤
n
1\leq n \leq 10^6,1\leq m\leq n
1≤n≤106,1≤m≤n
题解:
尺取后右端点值减左端点值即可,每次尺取保证有
m
m
m个不同的天,且窗口左端点和右端点不同即可,(中间相同的部分选任意一个都可)本题数据极弱,什么假做法都能过也是醉了。
每次尺取往右加
1
1
1后,将左端点往右至与右端点不同即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m;
int st[N];
int q[N];
struct Node{
int id, v;
bool operator < (const Node &A) const {
return v < A.v;
}
}p[N];
int main()
{
int g = 0;
scanf("%d%d", &n, &m);
for(int i = 1, cnt; i <= n; i++) {
scanf("%d", &cnt);
for(int j = 1, x; j <= cnt; j++) {
scanf("%d", &x);
p[++g] = {i, x};
}
}
sort(p + 1, p + 1 + g);
int l = 1, r = 0, cnt = 0;
while(r < g && cnt < m) {
++r;
++st[p[r].id];
if(st[p[r].id] == 1) ++cnt;
} //第一次的左右端点
int ans = 0x3f3f3f3f;
while(r <= g) {
ans = min(ans, p[r].v - p[l].v);
--st[p[l].id];
if(r < g) ++st[p[r + 1].id];
if(st[p[l].id] == 0) --cnt; //先更新l,r第一次
++l, ++r;
while(r < g && cnt < m) {
++r;
++st[p[r].id];
if(st[p[r].id] == 1) ++cnt;
}
while(st[p[l].id] > 1) --st[p[l].id], ++l; //保证左右一定不同
}
printf("%d\n", ans);
return 0;
}