【SPOJ DQUERY】区间数字统计

【链接】 我是链接,点我呀:)
【题意】

题意

【题解】

因为区间的端点移动一个单位的话,只会涉及到一个元素的增多或减少。 因此可以用莫队算法来解决。 只需要开一个数组(大小1百万),用下标来快速检索元素的个数即可。

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std;

struct abc{
    int l,r,id;
};
const int N = 30000;
const int Q = 200000;

int cnt[1000000+10];

abc query[Q+10];
int n,q,a[N+10];
int ans[Q+10],cur = 0;

bool cmp(abc a,abc b){
    if (a.l/200==b.l/200){
        return a.r<b.r;
    }else{
        return a.l<b.l;
    }
}

int main(){
    //freopen("D:\\rush.txt","r",stdin);
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i];
    cin >> q;
    for (int i = 1;i <= q;i++){
        int l,r;
        cin >> l >> r;
        query[i].l = l;query[i].r = r;query[i].id = i;
    }
    sort(query+1,query+1+q,cmp);
    int nowl = query[1].l,nowr = query[1].r;
    for (int i = nowl;i<=nowr;i++){
        cnt[a[i]]++;
        if (cnt[a[i]]==1){
            cur++;
        }
    }
    for (int i = 1;i <= Q;i++){
        while (nowl<query[i].l){
            cnt[a[nowl]]--;
            if (cnt[a[nowl]]==0) cur--;
            nowl++;
        }
        while (nowl>query[i].l){
            nowl--;
            cnt[a[nowl]]++;
            if (cnt[a[nowl]]==1) cur++;
        }
        while (nowr<query[i].r){
            nowr++;
            cnt[a[nowr]]++;
            if (cnt[a[nowr]]==1) cur++;
        }
        while(nowr>query[i].r){
            cnt[a[nowr]]--;
            if (cnt[a[nowr]]==0) cur--;
            nowr--;
        }
        ans[query[i].id] = cur;
    }
    for (int i = 1;i <= q;i++){
        cout<<ans[i]<<endl;
    }
    return 0;
}

posted @ 2019-09-27 15:19  AWCXV  阅读(172)  评论(0编辑  收藏  举报