题目链接:https://vjudge.net/problem/UVA-12174
取一个S长度的区间,用区间法扫描一遍序列,判断是否有冲突,把冲突区间对应的解法标0,最多有S种解法,用一个数组标记就行
判断冲突要用一个数组保存区间中各个歌曲的数量,和一个数保存不同歌曲数量,随着区间移动更新
这样时间复杂度为O(n)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<string>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int num[N],a[N];
bool vis[N];
int n,s;
int main()
{
//freopen("/home/zlwang/Desktop/t2.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&s,&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int pl=n-1,pr=pl+s,sum=0; //用pl,pr标记区间
memset(vis,true,sizeof(vis));
memset(num,0,sizeof(num)); //保存每首歌在区间中的数量
while(pr>0)
{
if(pl>=0)
{
if(num[a[pl]]==0) sum++; //更新区间中不同歌曲数
num[a[pl]]++;
}
if(pr<n)
{
num[a[pr]]--;
if(num[a[pr]]==0) sum--;
}
if(min(pr,n)-max(pl,0)!=sum) //判断是否有重复歌曲
{
int v=(n-pl)%s; //将对应区间标0
vis[v]=false;
}
pl--;
pr--;
}
int ans=0;
for(int i=0;i<s;i++) //统计可行数
if(vis[i]) ans++;
printf("%d\n",ans);
}
return 0;
}