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

不是,你分析思路跟没分析一样

posted @ 2023-08-24 16:33  长安19路  阅读(18)  评论(0)    收藏  举报  来源