SPOJ - DQUERY(莫队算法)

A - D-query

题意:

  给出一个长度为n的序列,询问【l,r】区间一共有多少个不同的元素。

分析:

  莫队算法的模板题。

  学习资料:大佬博客

代码:

#include <map>
#include <queue>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=3e4+100;
const int maxv=1e6+100;
const int maxq=2e5+100;

int n,q,num,block_size;

int arr[maxn],cnt[maxv],ans[maxq];

struct Query {
    int l,r,id;
    bool operator < (const Query& rhs) const {
        if(l/block_size!=rhs.l/block_size){
            return l/block_size<rhs.l/block_size;
        }
        return r<rhs.r;
    }
};
Query query[maxq];

void add(int pos)
{
    cnt[arr[pos]]++;
    if(cnt[arr[pos]]==1){
        num++;
    }
}

void del(int pos)
{
    cnt[arr[pos]]--;
    if(cnt[arr[pos]]==0){
        num--;
    }
}

int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        num=0;
        cls(cnt);
        block_size=sqrt(n);

        for(int i=1;i<=n;i++){
            scanf("%d",&arr[i]);
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            query[i].id=i;
            scanf("%d%d",&query[i].l,&query[i].r);
        }

        sort(query+1,query+q+1);
        int L=query[1].l,R=L-1;
        for(int i=1;i<=q;i++){
            while(L>query[i].l) add(--L);
            while(L<query[i].l) del(L++);
            while(R<query[i].r) add(++R);
            while(R>query[i].r) del(R--);
            ans[query[i].id]=num;
        }

        for(int i=1;i<=q;i++){
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}
View Code

posted on 2018-08-02 09:42  我过了样例耶  阅读(126)  评论(0编辑  收藏  举报

导航