HH的項鍊----樹狀陣列
阿新 • • 發佈:2018-12-12
文章目錄
題目描述
思路
某一段貝殼中,包含了多少種不同的貝殼?
最開始看見這道題時,沒有思路
但再看看,可以非常明瞭的發現這是一個樹狀陣列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;
}