codeforces 813e 莫队算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011528035/article/details/73938620

题意:给你一个区间 问你有总共多少个元素 ? 但是有一个条件 就是如果这个元素超过k个 当k个来算

思路:由于题目限制,所以只能是在线算法。如果知道一个区间,往左端加入一个点,只要知道这个的往右数第k个和它相同的数是否在这个区间么就可以了,右端同理。然后计算了一下复杂度和条件,发现可以使用莫队算法。

ps:其实可以使用在线的主席树,当时没想到,而且由于只记得莫队算法的思想,所以写了一个奇怪(偷懒版)的莫队算法,姿势其实并不标准,网络上有很多讲解的。


#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
using namespace std;

#define LL long long
#define MAX 100010

vector<int> f[MAX];
vector<int> b[MAX];

int l[MAX];
int r[MAX];

int s[400][400];
int a[MAX];

int v[MAX];

int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        f[a[i]].push_back(i);
        if(f[a[i]].size()>k)
        {
            l[i]=f[a[i]][f[a[i]].size()-k-1];
        }
    }
    for(int i=n;i>=1;i--)
    {
        b[a[i]].push_back(i);
        if(b[a[i]].size()>k)
        {
            r[i]=b[a[i]][b[a[i]].size()-k-1];
        }
        else
            r[i]=n+1;
    }
    for(int i=0;i*300<n;i++)
    {

        int sum=0;
        memset(v,0,sizeof(v));

        for(int j=i*300+1;j<=n;j++)
        {
            v[a[j]]++;
            if(v[a[j]]<=k)
                sum++;
            if(j%300==0)
                s[i][j/300]=sum;
        }
    }
    int m,x,y;
    int ans=0;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&y);
        x=(ans+x)%n+1;
        y=(ans+y)%n+1;

        if(x>y)
            swap(x,y);

        if(y-x<600)
        {
            ans=0;
            memset(v,0,sizeof(v));

            for(int j=x;j<=y;j++)
            {
                v[a[j]]++;
                if(v[a[j]]<=k)
                    ans++;
            }
        }
        else{
            int nowl=(x/300+1)-(x%300==1);
            int nowr=y/300;

            ans=s[nowl][nowr];

            int L=nowl*300+1;
            int R=nowr*300;

            while(L>x){
                L--;
                if(r[L]>R)
                    ans++;

            }

            while(R<y){
                R++;
                if(l[R]<x)
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
	return 0;
}


猜你喜欢

转载自blog.csdn.net/u011528035/article/details/73938620
今日推荐