2017 计蒜之道 初赛 第五场 D. UCloud 的安全秘钥(困难)

小数据打表,大数据暴力。

导致超时的主要原因是$m$小的询问次数太多,可以把$m≤10$的答案直接暴力打表存起来,$m>10$的用$C$题的方法即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
using namespace std;

int n,m;
int s[100010];
int t[100010];

int m1[100010];
int m2[100010];

map<vector<int>,int>ans;

void work()
{
	vector<int>vv;
	for(int i=1;i<=m;i++)
	{
		vv.push_back(t[i]);
	}
	sort(vv.begin(),vv.end());
	printf("%d\n",ans[vv]);
}

int main()
{
	scanf("%d",&n);

	for(int i=1;i<=n;i++) scanf("%d",&s[i]);

	for(int i=1;i<=n;i++)
	{
		vector<int>vv;
		for(int j=i;j<=i+10-1;j++)
		{
			vv.push_back(s[j]);
			sort(vv.begin(),vv.end());
			ans[vv]++;
		}
	}

	int Q; scanf("%d",&Q);
	
	while(Q--)
	{
		scanf("%d",&m);
		for(int i=1;i<=m;i++) scanf("%d",&t[i]);

		if(m>n)
		{
			printf("0\n");
			continue;
		}

		if(m<=10)
		{
			work();
			continue;
		}

		memset(m1,0,sizeof m1);
		memset(m2,0,sizeof m2);

		for(int i=1;i<=m;i++) m1[s[i]]++, m2[t[i]]++;

		int bu = 0;
		for(int i=1;i<=n;i++) if(m1[i]!=m2[i]) bu++;

		int ans = 0;
		if(bu == 0) ans++;

		for(int i=m+1;i<=n;i++)
		{
			int pre = i-m;
			int now = i;

			if(m1[s[pre]] == m2[s[pre]]) bu++;
			else if(m1[s[pre]]-1 == m2[s[pre]]) bu--;
			
			m1[s[pre]]--;

			if(m1[s[now]] == m2[s[now]]) bu++;
			else if(m1[s[now]]+1 == m2[s[now]]) bu--;
			
			m1[s[now]]++;

			if(bu == 0) ans++;

		}

		printf("%d\n",ans);
	}

	return 0;
}
posted @ 2017-06-03 20:47 Fighting_Heart 阅读(...) 评论(...) 编辑 收藏