首页 > 代码库 > 2017 计蒜之道 初赛 第五场 D. UCloud 的安全秘钥(困难)

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

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