1. 程式人生 > 實用技巧 >BZOJ 1878 [SDOI2009]HH的項鍊(莫隊演算法)

BZOJ 1878 [SDOI2009]HH的項鍊(莫隊演算法)

題意:給出長度為n的序列a,給出m組詢問,問L-R區間的數字種類個數,離線詢問。n<2e5,a[i]<1e6

題解:莫隊模板,注意就是用奇偶性排序可加快,和block=n/sqrt(m*2/3)。複雜度:nlogn

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("C:\\in.txt", "r", stdin)
#define _for(i,a,b) for(int i=a; i< b; i++)
#define _rep(i,a,b) for(int i=a; i<=b; i++)
#define
lowbit(a) ((a)&-(a)) #define inf 0x3f3f3f3f #define endl "\n" using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10
+c-'0'; if(op) x=-x; } const int maxn=5e5+5; int T, n, m, a[maxn]; int res, num[1000005], ans[maxn]; //這裡WA一次,a【i】的範圍 struct Node{ int l, r, idx; }q[maxn]; int block; bool cmp(Node x, Node y){ return (x.l/block)^(y.l/block)? x.l<y.l : (((x.l/block)&1)? x.r<y.r : x.r>y.r); } void add(int
x){ if(!num[a[x]]) res++; num[a[x]]++; } void del(int x){ num[a[x]]--; if(!num[a[x]]) res--; } int main() { //read(T); T=1; while(T--) { read(n); memset(num, 0, sizeof(num)); res=0; _rep(i, 1, n) read(a[i]); read(m); _rep(i, 1, m) read(q[i].l), read(q[i].r), q[i].idx=i; block=n/sqrt(m*2/3); sort(q+1, q+1+m, cmp); int l=0, r=0; _rep(i, 1, m){ int ql=q[i].l, qr=q[i].r; while(l<ql) del(l++); while(l>ql) add(--l); while(r<qr) add(++r); while(r>qr) del(r--); ans[q[i].idx]=res; } _rep(i, 1, m) printf("%d\n", ans[i]); } return 0; }