洛谷 P6465 [传智杯 #2 决赛] 课程安排

题意

给定一个数组 \(a\) , 长度 \(l\) , 求连续的子序列个数使得子序列中没有相邻相同的元素 , 且子序列长度大于 \(l\)

特别的 , 首尾元素被认为是相邻的

思路

求连续的子序列考虑双指针 , 序列需要满足两个条件:

  • 无相邻元素

  • 长度大于 \(l\)

求子序列数目就是求 \(i\) , \(j\) , 使得 \(a_i\)\(a_j\) 满足某种条件

而通常这种双重枚举的 \(O(n^2)\) 的优化方向就是枚举各个点所能贡献出的答案

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
int n,m;
const int N = 5e5+10;
int a[N];
int cnt[N];
signed main() {
    int t = read();
    while (t--)
    {
        memset(cnt,0,sizeof cnt);
        n =read();
        m =read();
        int ans = 0;
        for (int i= 1; i<= n; i++)a[i] =read();
        int j = 0;
        for (int i =1; i< n; i++) {
            for (;j<n && (a[j]!=a[j+1]||j<i);) {
                ++j;
                if (j>=i+m-1) {
                    cnt[a[j]]++;
                }
            }
            ans+= max(0ll,j-(i+m-1)+1-cnt[a[i]]);
            if (j>=i+m-1)
                cnt[a[i+m-1]]--;

        }
        cout<<ans<<"\n";
    }
    return 0;
}
posted @ 2025-03-15 18:34  Guaninf  阅读(7)  评论(0)    收藏  举报