[luogu1972][SDOI2009]HH的項鍊
阿新 • • 發佈:2018-12-05
開始用莫隊水了90分。
想了很久還是沒想出來,於是看了一眼題解。妙!實在妙!
考慮一個數字只被算一次?那麼其他的數應該被刪掉。
對於一個固定的右區間端點,顯然刪的數越往後越好。
於是考慮把所有詢問的區間按右端點排序,然後開始掃一遍。用樹狀陣列維護字首和。
#include <cstdio> #include <cstring> #include <algorithm> #define lowbit(x) (x&(-x)) #define MAXN 500005 struct Node { int l,r,num; }G[MAXN]; int C[MAXN<<1],a[MAXN],book[MAXN<<1]; int ans[MAXN]; int N,M; inline bool cmp(Node a,Node b) { return a.r<b.r; } inline void update(int x,int u) { for(;x<=N;x+=lowbit(x)) C[x] += u; } inline int query(int u) { int ans = 0; for(;u>=1;u-=lowbit(u)) ans += C[u]; return ans; } int main() { std::memset(book,0,sizeof(book)); scanf("%d",&N); for(int i=1;i<=N;++i) { scanf("%d",&a[i]); } scanf("%d",&M); for(int i=1;i<=M;++i) { scanf("%d%d",&G[i].l,&G[i].r); G[i].num = i; } std::sort(G+1,G+1+M,cmp); int last = 0; for(int i=1;i<=M;++i) { for(;last+1<=G[i].r;) { last++; if(book[a[last]]) update(book[a[last]],-1); book[a[last]] = last; update(last,1); } ans[G[i].num] = query(G[i].r) - query(G[i].l-1); } for(int i=1;i<=M;++i) printf("%d\n",ans[i]); return 0; }