2020牛客暑期多校训练营Groundhog Looking Dowdy(滑动窗口,贪心)

Groundhog Looking Dowdy

题目描述

2020牛客暑期多校训练营Groundhog Looking Dowdy(滑动窗口,贪心)_第1张图片

样例

input:
4 3
1 3
2 8 6
1 2
3 1 7 5
output:
2

题目大意

n n n天,每天土拨鼠有一些衣服可以穿。其中 m m m天他要出去见 A p p l e Apple Apple,因此他希望穿一些更特别的衣服。每件衣服都有一个 d o w d i n e s s dowdiness dowdiness不时髦度。现在土拨鼠希望对于任意的 m m m天每天找到一件衣服使得选出的这些衣服中 d o w d i n e s s dowdiness dowdiness的最大值和最小值的差的最小值。

分析

由于是最大值和最小的差最小,那么第一步肯定是要存储下来的。但是有个问题,看到 k k k n n n的范围,傻了,这肯定是不能用二维的数组存储的啊。但是我一看到这个:
t h e   s u m   o f   t h e   c l o t h e s   ≤ 2 ∗ 1 0 6 the\,sum\,of\,the\,clothes\,\le2*10^6 thesumoftheclothes2106
那用一维的存一下肯定是莫得问题的。那么我们来想想,可以存在一维的吗?

显然,如果只是存储 d o w d i n e s s dowdiness dowdiness是不对的,因为如果是同一天的衣服肯定是不能同时选的。那么我们可以把每件衣服都打一个标记,记录一下是从哪一天来的。然后我们只要对已经存储了的衣服对于 d o w d i n e s s dowdiness dowdiness进行排序,然后在里面维护一个来自不同的天的个数为 m m m就可以了,这些衣服的 d o w d i n e s s dowdiness dowdiness必定是大于左端点小于右端点的。

复杂度 O ( n ) O(n) O(n),快速 A C AC AC
据说有的人用最小值排序就水过去了,过分啊

代码

#include
#define ll long long
using namespace std;
const int MAXN=2e6+10;
struct node{
	int v,from;
}a[MAXN];//v 不时髦度 from 来自哪一天
bool cmp(node x,node y){return x.v<y.v;}
int m,cnt=0;
int vis[MAXN];//标记每一天在当前窗口出现的次数
int main()
{
	int n,k;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&k);
		for(int j=1;j<=k;j++){
			cnt++;scanf("%d",&a[cnt].v);
			a[cnt].from=i;
		}
	}
	sort(a+1,a+1+cnt,cmp);
	int ans=1e9,l=1,r=m,tmp=0;
	for(int i=l;i<=r;i++){
		if(!vis[a[i].from]) tmp++;//要先加种类,然后无论怎么样都要加上天数的个数
		vis[a[i].from]++;//一开始这里沙雕了
	}
	while(tmp<m){r++;if(!vis[a[r].from]) tmp++;vis[a[r].from]++;}//处理第一个区间
	for(l,r;r<=cnt;){
		ans=min(ans,a[r].v-a[l].v);
		vis[a[l].from]--;l++;//左端点
		if(vis[a[l-1].from]==0) tmp--;
		while(tmp<m&&r<=cnt){r++;if(!vis[a[r].from]) tmp++;vis[a[r].from]++;}
	}
	printf("%d",ans);
}

END

这题用到了贪心,就是排序啊。

感谢ccsu_Tomcat的hack数据,及时纠正了沙雕。特此鸣谢~

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