CF352B题解
对于我这种蒟蒻都能一遍 AC 的水题嘛,我要不然放个代码就跑吧~~~
算了,还是老老实实分析题意。
对于 如此小的可怕的数据范围,显然我们可以开一个结构体,分别存储每个元素在数组里出现的上一个数的位置,等差数列的差,这个数出现的次数和当前成立与否。
然后 $O(n)$ 扫一遍,特判一下某个数第一次和第二次出现一定成立就好。
最后 $O(n)$ 扫两遍,分别统计成立数字的个数,然后再输出。
具体实现看代码,自以为注释挺详细的。
#include<iostream>
using namespace std;
int n, maxn;
int a[100005];
struct Node{
int last;//上一个数是几
int cha;//等差数列的差是几
int num;//这个数出现了几次
bool flag = true;//这个数成立与否
}ans[100005];
int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
maxn = max(maxn, a[i]);//找到最大的a[i]
}
for(int i = 1; i <= n; i++){
if(ans[a[i]].flag == false)//在之前的判断中已经不成立了
continue;//直接退出
else if(ans[a[i]].num == 0)//这个数是第一次出现
ans[a[i]].last = i,//起始位置是i
ans[a[i]].num++,
ans[a[i]].cha = 0;
else if(ans[a[i]].num == 1){//有一个数了,是第二次出现
ans[a[i]].cha = i - ans[a[i]].last,//标记差值
ans[a[i]].last = i,//标记元素
ans[a[i]].num++;//个数++
}
else{//出现过多次了
if(i - ans[a[i]].last != ans[a[i]].cha)//不成立
ans[a[i]].flag = false;//此时不用做别的处理,因为!flag后都没有意义了
else
ans[a[i]].last = i,//继续更新
ans[a[i]].num++;
}
}
int cnt = 0;
for(int i = 1; i <= maxn; i++)
if(ans[i].num && ans[i].flag)
cnt++;
printf("%d\n",cnt);
for(int i = 1; i <= maxn; i++)
if(ans[i].num && ans[i].flag)
printf("%d %d\n", i, ans[i].cha);
return 0;
}
不是,你分析思路跟没分析一样

浙公网安备 33010602011771号