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