题意 求区间内出现一共有几种数字。
上次写了一个主席树,这次用一下莫队,莫队是离线询问的一种操作,将询问分块,如果在同一个块内就按照右端点排序,如果不在同一个块内就按照块的位置大小排序。
代码:
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 }