转载声明:http://blog.csdn.net/keshuai19940722/article/details/19292045
个人想法:这道题几乎花了我一天的时间,想出算法来,可是无情的wa了,自己想了想例子
(4 8)
(3 2 4 1 3 2 3 2) 直接把我的想法推倒,简直无力,无奈的请教题解了,我转载的这篇文章是我看到写法比较清晰的文章了.先说说我的想法吧, 首先我一看到连续的 我会自动想到滑动窗口, 可是我的算法会划分出【3 2 4 1】【3 2】【3 2】 这样的就是错误的 因为 对于一串数字是否合法, 我认为只会出现这样的情况 假设 [唯一] 代表 满足s,而且里面的数字都是唯一的窗口, 【不唯一】代表 不满足s 但数字是唯一的窗口,那么无非就是 【不唯一】/[唯一] +[唯一]* +(【不唯一】/[唯一])^(0…1) 个这样组成的数字串,凡是不符合这个公式的串 都不合法, 可能是我算法用了贪心的原因,我在分析数字串结构式就分析出来这样的方式,果断wa…
分析:首先用滑动窗口在o(n) 时间内求出 以i为开头的连续s个的序列中是否满足都是[唯一]的,然后枚举前s个开头,如果 i+=s ,i<=n的所有区间都满足[唯一]性,则当前位置可以划分.我感觉这个技巧好有意思啊…太蠢了居然没想到。
代码:
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
const int maxn=100000+10;
int s,n;
int T;
int p[maxn],c[maxn];
bool flag[maxn];
void init()
{
memset(flag, 0, sizeof(flag));
memset(c, 0, sizeof(c));
scanf("%d%d",&s,&n);
int tmp=0;
for(int i=0;i<n;i++)
{
scanf("%d",&p[i]);
if(i<s)
{
if(c[p[i]])tmp++;
c[p[i]]++;
}
}
for (int i = 0; i < n; i++)
{
if (tmp == 0) flag[i] = true;
if (c[p[i]] == 2) tmp--;
c[p[i]]--;
int k = i + s;
if (k >= n) continue;
if (c[p[k]]) tmp++;
c[p[k]]++;
}
}
bool judge(int x)
{
for(int i=x;i<n;i+=s) if(!flag[i])return false;
return true;
}
int solve()
{
int ans=0;
memset(c,0,sizeof(c));
for(int i=0;i<s;i++)
{
if(judge(i))ans++;
if(i>=n) continue;
if(c[p[i]])break;
c[p[i]]++;
}
return ans;
}
int main()
{
#ifdef OUT
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
scanf("%d",&T);
while(T--)
{
init();
printf("%d\n",solve());
}
return 0;
}