傳送門啦
分析:
題目描述不說了,大意是,求一段區間內不同元素的種數。
看到區間,我們大概先想到的是暴力(然後炸掉)、線段樹、樹狀陣列、分塊。
下面給出的是一種樹狀陣列的想法。
首先,對於每一段區間裡的數,如果出現重複的元素,我們只需要看最後乙個就好了。所以,我們可以對所有需要查詢區間的右端點進行從小到大的排序,從左往右列舉右端點維護乙個從左向右的樹狀陣列,表示一段區間的種類數。
聽不懂的話我們舉個栗子例子。
我們假設現在有乙個序列:
now為現在的右端點;
insert(i , j)表示在第i個位置出現了j個位重複的數,就需要我們在我們維護的樹狀陣列序列中+j。
1 ,2 ,1 ,3
當now = 1時,insert(1 , 1),樹狀陣列對應的序列就變成了1,0,0,0
當now = 2,insert(2,1),序列變成了1,1,0,0
當now = 3時,我們發現a[3]=1,而1之前已經出現過了,所以最後一次出現的地方(a[1])減1,即insert(1,−1),a[3]這個地方加1,即insert(3,1),序列變成了0,1,1,0
當now = 4時,insert(4 , 1),序列變成0,1,1,1
這樣的話,我們列舉ii的時候處理一下就ok了.
最後whilewhile輸出sum[ ](類似字首和的乙個陣列如果查詢區間[3~5],就變成sum[5]−sum[2])。
你會發現**中還有乙個last[ ],last[i]根據我的解釋應該很好懂吧,表示的就是ii這個元素最後出現的位置。。
好了,**奉上。。
#include #include#include
#include
using
namespace
std;
const
int maxn = 1000005
;inline
intread()
while(ch >= '
0' && ch <= '9')
return x *f;
}int
n,a[maxn],m;
struct
edgee[maxn
<< 2
];int
last[maxn],sum[maxn],ans[maxn];
inttmp;
bool cmp(edge a,edge b)
int lowbit(int x)
void insert(int x,int
v)int query(int
x)int
main()
sort(e + 1 , e + 1 +m , cmp);
int now = 1
;
for(int i=1;i<=n;i++)
}for(int i=1;i<=m;i++)
printf(
"%d\n
",ans[i]);
return0;
}
洛谷 P1972 HH的項鍊
題意 查詢某一區間顏色數 思路 對於固定區間來說,顏色數隻與各種顏色第一次出現的位置有關。該位置置1,該顏色其餘位置置0.include using namespace std typedef long long ll typedef pairpii typedef pairpiii const l...
洛谷P1972 HH的項鍊 樹狀陣列
題目 題意 給定乙個長度為n的序列,數字表示珠子的種類。m次查詢每次詢問給定區間內珠子的種類數。思路 可以說是運用了字首和的思想吧。從前到後的去處理查詢,而對於某乙個查詢區間,如果某乙個種類出現了多次的話我們只需要計算最後一次出現。用query x 表示1 x區間內的種類數,其中對每個種類我們只標記...
樹狀陣列 洛谷 P1972 HH的項鍊
hh 有一串由各種漂亮的貝殼組成的項鍊。hh 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。hh 不斷地收集新的貝殼,因此,他的項鍊變得越來越長。有一天,他突然提出了乙個問題 某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答 因為項鍊實在是太長了。於...