1. 程式人生 > >HH的項鍊----樹狀陣列

HH的項鍊----樹狀陣列

文章目錄

題目描述

點這裡

思路

某一段貝殼中,包含了多少種不同的貝殼?

最開始看見這道題時,沒有思路

但再看看,可以非常明瞭的發現這是一個樹狀陣列ban

設有一長為5的項鍊

1 2 3 2 1

然後 m = 3

1 5

2 5

1 3

我的思路是這樣,由於要求的是種類數 != 求l 到 r 的個數

每種貝殼只能存一個(不能反覆存)

也就是說必須刪去一些相同的貝殼

刪除的不能影響求得答案

比如:上面的1 2 3 2 1,去重,用-1表示刪去的

1 2 3 -1 -1

如果像這樣,求 l=2,r=5時結果為2

而實際結果為3

所以我們得排個序,按r的升序

遍歷i,當i所在位置貝殼前面沒有時,update(i,1)

否則update(i,1)且刪去前一個

所以又需要一個數組Glod來記錄前一個貝殼的地址

便有了如下程式碼

code

#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 500001
; const int NUM = 1000001; int n,Bit[MAXN],Pr[MAXN],Glod[MAXN]; int k[NUM]; inline void Read(int *x) { *x = 0; char a = getchar(); bool f = 0; while(a < '0'||a > '9') {if(a == '-') f = 1;a = getchar();} while(a >= '0'&&a <= '9') {*x = *x * 10 + a - '0';a = getchar();} if(f) *x *= -
1; } class T { int lowbit(int x) { return x & (-x); } public: bool operator <(const T w) const { if(r < w.r) return 1; if(r == w.r) if(l < w.l) return 1; return 0; } int l,r,num; void update(int,int); int Sum(int); }a[MAXN]; void T::update(int Index,int delta) { int i = Index; for(;i <= n;i += lowbit(i)) Bit[i] += delta; } int T::Sum(int Index) { int ans = 0,i = Index; for(;i > 0;i -= lowbit(i)) ans += Bit[i]; return ans; } int main() { int i,m; Read(&n); for(i = 1;i <= n;i++) scanf("%d",&Glod[i]); Read(&m); for(i = 1;i <= m;i++) { Read(&a[i].l),Read(&a[i].r); a[i].num = i; } sort(a + 1,a + 1 + m); int q = 1; for(i = 1;i <= a[m].r;i++) { if(!k[Glod[i]]) { k[Glod[i]] = i; a[i].update(i,1); } else { a[i].update(k[Glod[i]],-1); k[Glod[i]] = i; a[i].update(i,1); } while(i == a[q].r) { Pr[a[q].num] = a[q].Sum(a[q].r) - a[q].Sum(a[q].l - 1); q++; } } for(i = 1;i < m;i++) printf("%d\n",Pr[i]); printf("%d",Pr[m]); return 0; }