2020牛客多校第九场 F.Groundhog Looking Dowdy 尺取

题意:
给定 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 1n106,1mn

题解:
尺取后右端点值减左端点值即可,每次尺取保证有 m m m个不同的天,且窗口左端点和右端点不同即可,(中间相同的部分选任意一个都可)本题数据极弱,什么假做法都能过也是醉了。
每次尺取往右加 1 1 1后,将左端点往右至与右端点不同即可。

代码:

#include
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;
}

你可能感兴趣的:(多校)