CF1120A Diana and Liana :尺取法

题意:

  • m朵花,从第一个开始,按顺序每k个做成一个花圈,一共要做n个。其中一个要满足条件:必须包含要求的s种。
  • 移掉几朵花,使产生规定的花圈,并且可以做成n个。

题解: 

  • 先找到一个区间[l,r],满足r-l+1≥k并且有要求的s种花。并且前面的l-1朵花是k的倍数,如果不是,那么就要移走(l-1)%k朵花,也就是移走区间[(l-1)/k*k,l)的花。并且移走的花的数量要≤m-n*k。

代码:

#include <bits/stdc++.h>
using namespace std;
int const N = 500000 + 10;
int m,n,k,s,limit;
int a[N],b[N],need[N],num[N];
int main(){
	scanf("%d%d%d%d",&m,&k,&n,&s);
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);    
	for(int i=1;i<=s;i++){
		int  tmp;	scanf("%d",&tmp);
		need[tmp]++;
	}
	int l = 1,r = 0,cnt = 0;
	bool flag = false;
	while(r < m && !flag){
		while(r < m && (r - l + 1 < k || cnt < s))  //!(r - l + 1 >= k && cnt >= s)
			if(++num[a[++r]] <= need[a[r]])	cnt++;
		while(l <= r && (l - 1) % k + (r - l + 1) - k > m - n * k){
			num[a[l++]]--;
			if(num[a[l-1]] < need[a[l-1]]){
				cnt--;
			 	break;
			}
		}
		if(cnt == s)	flag = true;
	}
	if(!flag)	printf("%d\n",-1);
	else{
		int res = m - n * k - (r - l + 1- k);  //两侧要移走的花
		printf("%d\n",m - n * k);
		for(int i=(l-1)/k*k+1;i<l;i++)	printf("%d ",i),	res--;
		cnt = 0;
		for(int i=l;i<=r;i++){
			if(r - l + 1 - cnt <= k)	break;
			if(need[a[i]] < num[a[i]])
				printf("%d ",i),	num[a[i]]--,	cnt++;
		}
		for(int i=r+1;i<=m;i++)	if(res)		printf("%d ",i),	res--;

	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/88827418