D-query

SPOJ - DQUERY

题意 求区间内出现一共有几种数字。

上次写了一个主席树,这次用一下莫队,莫队是离线询问的一种操作,将询问分块,如果在同一个块内就按照右端点排序,如果不在同一个块内就按照块的位置大小排序。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define max3(a,b,c) max(a,max(b,c))
12 #define min3(a,b,c) min(a,min(b,c))
13 #define _S(X) cout << x << ' ';
14 #define __S(x) cout << x << endl;
15 typedef pair<int,int> pll;
16 const int INF = 0x3f3f3f3f;
17 const LL mod =  (int)1e9+7;
18 const int N = 2e5 + 100;
19 int cnt[N*5];
20 int a[N*2];
21 int ans;
22 int m;
23 int Ans[N];
24 struct Node{
25     int l, r, id;
26 }q[N];
27 
28 inline void Add(int p){
29     cnt[a[p]]++;
30     if(cnt[a[p]] == 1) ans++;
31 }
32 inline void Remove(int p){
33     cnt[a[p]]--;
34     if(!cnt[a[p]]) ans--;
35 }
36 inline bool cmp(Node x1, Node x2){
37     if(x1.l/m != x2.l/m){
38         return x1.l/m < x2.l/m;
39     }
40     return x1.r < x2.r;
41 }
42 int main(){
43     int n;
44     scanf("%d", &n);
45     m = sqrt(n);
46     for(int i = 1; i <= n; i++)
47         scanf("%d", &a[i]);
48     int p;
49     scanf("%d", &p);
50     for(int i = 1; i <= p; i++){
51         scanf("%d%d", &q[i].l, &q[i].r);
52         q[i].id = i;
53     }
54     sort(q+1, q+1+p, cmp);
55     int L = 0, R = 0;
56     for(int i = 1; i <= p; i++){
57         int tL = q[i].l, tR = q[i].r;
58         while(L < tL) Remove(L++);
59         while(L > tL) Add(--L);
60         while(R <= tR) Add(R++);
61         while(R > tR + 1) Remove(--R);
62         Ans[q[i].id] = ans;
63     }
64     for(int i = 1; i <= p; i++){
65         printf("%d
", Ans[i]);
66     }
67     return 0;
68 }
D-query
原文地址:https://www.cnblogs.com/MingSD/p/9122083.html