A. Diana and Liana

A. Diana and Liana

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
At the first holiday in spring, the town Shortriver traditionally conducts a flower festival. Townsfolk wear traditional wreaths during these festivals. Each wreath contains exactly k flowers.

The work material for the wreaths for all n citizens of Shortriver is cut from the longest flowered liana that grew in the town that year. Liana is a sequence a1, a2, …, am, where ai is an integer that denotes the type of flower at the position i. This year the liana is very long (m≥n⋅k), and that means every citizen will get a wreath.

Very soon the liana will be inserted into a special cutting machine in order to make work material for wreaths. The machine works in a simple manner: it cuts k flowers from the beginning of the liana, then another k flowers and so on. Each such piece of k flowers is called a workpiece. The machine works until there are less than k flowers on the liana.

Diana has found a weaving schematic for the most beautiful wreath imaginable. In order to weave it, k flowers must contain flowers of types b1, b2, …, bs, while other can be of any type. If a type appears in this sequence several times, there should be at least that many flowers of that type as the number of occurrences of this flower in the sequence. The order of the flowers in a workpiece does not matter.

Diana has a chance to remove some flowers from the liana before it is inserted into the cutting machine. She can remove flowers from any part of the liana without breaking liana into pieces. If Diana removes too many flowers, it may happen so that some of the citizens do not get a wreath. Could some flowers be removed from the liana so that at least one workpiece would conform to the schematic and machine would still be able to create at least n workpieces?

Input
The first line contains four integers m, k, n and s (1≤n,k,m≤5⋅105, k⋅n≤m, 1≤s≤k): the number of flowers on the liana, the number of flowers in one wreath, the amount of citizens and the length of Diana’s flower sequence respectively.

The second line contains m integers a1, a2, …, am (1≤ai≤5⋅105) — types of flowers on the liana.

The third line contains s integers b1, b2, …, bs (1≤bi≤5⋅105) — the sequence in Diana’s schematic.

Output
If it’s impossible to remove some of the flowers so that there would be at least n workpieces and at least one of them fullfills Diana’s schematic requirements, output −1.

Otherwise in the first line output one integer d — the number of flowers to be removed by Diana.

In the next line output d different integers — the positions of the flowers to be removed.

If there are multiple answers, print any.

Examples
input
7 3 2 2
1 2 3 3 2 1 2
2 2
output
1
4
input
13 4 3 3
3 2 6 4 1 4 4 7 1 3 3 2 4
4 3 4
output
-1
input
13 4 1 3
3 2 6 4 1 4 4 7 1 3 3 2 4
4 3 4
output
9
1 2 3 4 5 9 11 12 13
Note
In the first example, if you don’t remove any flowers, the machine would put out two workpieces with flower types [1,2,3] and [3,2,1]. Those workpieces don’t fit Diana’s schematic. But if you remove flower on 4-th place, the machine would output workpieces [1,2,3] and [2,1,2]. The second workpiece fits Diana’s schematic.

In the second example there is no way to remove flowers so that every citizen gets a wreath and Diana gets a workpiece that fits here schematic.

In the third example Diana is the only citizen of the town and that means she can, for example, just remove all flowers except the ones she needs.

先遍历数组,找到包含第一个 b 1 , b 2 , b 3 … … b s b_1,b_2,b_3……b_s b1,b2,b3bs数字的长度最短的子串。

我们把子串的第一个在a数组中的下标叫做pos,为了让这个子串正好被截到,我们要把子串往前移动 num1 = (pos - 1) %k个位置。
子串最后一个数字在a数组中的下标为ed,子串的长度为(ed - pos + 1),为了使子串被截,需要删去num2 =(ed - pos +1 - k)个数字

注意:如果这里需要删去的为负数,即子串长度比k小,则判断 num1 + num2 是否大于0。即把本来要前移的字符也当做子串的一部分。如果这样做还是比0小的话,表明a数组已经满足条件,不用再删去。

在num2<0 && num1 + num2 >0的情况下,将num1+=num2,num2 = 0即把子串向前移动(删去不必要的数字)
或者如果num2不为负数
在上面两种情况下,判断需要删去的字符num1+num2是否小于 m − k ∗ n m-k*n mkn,如果满足,则输出解,不满足就继续找。

寻找下一个包含 b 1 , b 2 , b 3 … … b s b_1,b_2,b_3……b_s b1,b2,b3bs数字的长度最短的子串。
我们开一个队列q存储 a数组中,属于b数组的数字 的位置下标。
找到子串时,q.front()是子串的第一位的下标,q.back()是子串末尾的位置下标。
寻找下一个子串时,q.pop(),然后判断剩下的子串是否满足b数组的要求。
满足就进行下一步的判断。
不满足的话就往后找,找到a[pos]或者a数组末尾为止。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#define ll long long 
using namespace std;

int a[500010],b[500010],c[500010],d[500010];
set<int> t,t1;

int main()
{
	int m,k,n,s;
	scanf("%d%d%d%d",&m,&k,&n,&s);
	int maxn = m - k * n;
	for (int i = 1;i<=m;i++) scanf("%d",&a[i]);
	for (int i = 1;i<=s;i++)
	{
		scanf("%d",&b[i]);
		t.insert(b[i]);
		t1.insert(b[i]);
		c[b[i]]++;
	}
	int i = 1;
	queue<int> q;
	while (i <= m)
	{
		if (t.count(a[i]) == 1)
		{
			d[a[i]]++;
			if (d[a[i]] >= c[a[i]]) t1.erase(a[i]);
			q.push(i);
		}
		if (t1.size() == 0) break;//如果已经找齐了 
		i++;
	}
	if (t1.size() != 0)
	{
		cout<<"-1";
		return 0;
	}
	while (i <= m)
	{
		int pos = q.front();
		int num1 = (pos - 1) % k;
		int num2 = (i - pos + 1) - k;
		if (num2 < 0)//如果找到的比k小 
		{
			if (num1 + num2 > 0)
			{
				num1 = num1 + num2;
				num2 = 0;
			}
			else num1 = num2 = 0;
		}
		if (maxn >= num1 + num2)
		{
			cout<<num1 + num2<<'\n';
			for (int j = pos - num1;j<pos;j++) printf("%d ",j);//字串前移,使其能够被k截断
			for (int j = pos;j<=i && num2 > 0;j++)//删去字串内部的数字,使其能够被k截断 
			{
				if (j == q.front())
				{
					if (d[a[j]] > c[a[j]])
					{
						printf("%d ",j);
						num2--;
						d[a[j]]--;
					}
					q.pop();
				}
				else
				{
					printf("%d ",j);
					num2--;
				}
			}
			return 0;
		}
		d[a[pos]]--;
		q.pop();
		if (d[a[pos]] >= c[a[pos]]) continue;//如果删去第一个pos,还是满足b数组的要求 
		else//如果不满足b数组的要求 
		{
			i++;
			while (i <= m)
			{
				if (t.count(a[i]) == 1)
				{
					d[a[i]]++;
					q.push(i);
					if (d[a[pos]] >= c[a[pos]]) break;
				}
				i++;
			}
			if (d[a[pos]] < c[a[pos]])//如果往后没有符合b要求的子串了 
			{
				printf("-1");
				return 0;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值