國家集訓隊2010 小Z的襪子 莫隊演算法

2021-08-03 18:09:09 字數 2975 閱讀 7378

作為乙個生活散漫的人,小z每天早上都要耗費很久從一堆五顏六色的襪子中找出一雙來穿。終於有一天,小z再也無法忍受這惱人的找襪子過程,於是他決定聽天由命……

具體來說,小z把這n只襪子從1到n編號,然後從編號l到r(l 儘管小z並不在意兩隻襪子是不是完整的一雙,甚至不在意兩隻襪子是否一左一右,他卻很在意襪子的顏色,畢竟穿兩隻不同色的襪子會很尷尬。

你的任務便是告訴小z,他有多大的概率抽到兩隻顏色相同的襪子。當然,小z希望這個概率盡量高,所以他可能會詢問多個(l,r)以方便自己選擇。

第一行包含兩個正整數n和m。n為襪子的數量,m為小z所提的詢問的數量。

接下來一行包含n個正整數ci,其中ci表示第i只襪子的顏色,相同的顏色用相同的數字表示。

再接下來m行,每行兩個正整數l,r表示乙個詢問。

包含m行,對於每個詢問在一行中輸出分數a/b表示從該詢問的區間[l,r]中隨機抽出兩隻襪子顏色相同的概率。若該概率為0則輸出0/1,否則輸出的a/b必須為最簡分數。(詳見樣例)

sample input

6 4

1 2 3 3 3 2

2 6

1 3

3 5

1 6sample output

2/5

0/1

1/1

4/15

樣例說明:

詢問1:共c(5,2)=10種可能,其中抽出兩個2有1種可能,抽出兩個3有3種可能,概率為(1+3)/10=4/10=2/5。

詢問2:共c(3,2)=3種可能,無法抽到顏色相同的襪子,概率為0/3=0/1。

詢問3:共c(3,2)=3種可能,均為抽出兩個3,概率為3/3=1/1。

注:上述c(a, b)表示組合數,組合數c(a, b)等價於在a個不同的物品中選取b個的選取方案數。

資料範圍:

30%的資料中 n,m ≤ 5000;

60%的資料中 n,m ≤ 25000;

100%的資料中 n,m ≤ 50000,1 ≤ l < r ≤ n,ci ≤ n。

第一次看到這題,第一想法是用線段樹或者樹狀陣列維護一下,但仔細一想,似乎不行,因為本題的區間不滿足加和性質。於是就需要用到莫隊演算法。

莫隊演算法可以解決已經知道區間[l,r]的答案,然後可以在o(1)(或者o(log n))的時間內求出[l,r+1],[l,r-1],[l-1,r],[l+1,r]的答案的問題。

現在知道,在區間[l,r]中,答案是

(x

2+y2

+z2.

....

..−(

r−l+

1))/

((r−

l+1)

(r−l

))(x,y,z分別代表區間中不同顏色襪子的個數)。

顯然,這是滿足上面的性質的。假如我們按照讀入順序依次求解的話,複雜度為o(

n2) ,不是特別滿意。

這時我們就需要用到莫隊演算法,莫隊演算法的核心就是改變求解詢問的順序,從而減少運算的次數。那麼,怎麼樣改變順序來使速度最快呢?可以把每個區間都看做2維平面上的點,這些點的距離為橫,縱座標之差,然後我們可以o(n logn)求出這些平面點的曼哈頓最小生成樹,但這樣太複雜(而且我也不會)。

所以我們可以用分塊來處理,將n分成sqrt(n)塊,然後我們維護一下左端點所在塊的編號。以左端點的編號為第一關鍵字,右端點的編號為第二關鍵字排序;然後以排序後的順序依次求解(所以是離線的),在求解的過程中維護答案的值。這樣做的複雜度為 o(

n∗n−

−√) 。以下是證明過程:

時間複雜度就是左右端點移動的次數。

對於右端點的移動:因為一共只有n−

−√個塊,每個塊中右端點最多移動n次,所以複雜度為o(

n∗n−

−√) 。

對於左端點的移動:如果在同一塊中移動,那麼是o(

n−−√

)的如果跨越了塊,那麼最多跨越o(

n),那麼複雜度為o(

n∗n−

−√+n

)

綜上,時間複雜度為o(

n∗n−

−√) 。

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define ll long long

#define rep(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)

#define drep(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)

#define erep(i,a) for(register int i=start[(a)];i;i=e[i].next)

inline

int read()

const

int maxn=5e4+20;

int n,m;

int w[maxn];

void init()

struct query ;

struct ans ;

query qu[maxn];

ans ans[maxn];

int k;

bool cmp(const query a,const query b)

;ll a;

void work(int x,int add)

void doing()

sort(qu+1,qu+m+1,cmp);

int l=1,r=0;

rep(i,1,m)

;continue;

}ans[qu[i].sx]=;

}rep(i,1,m)

國家集訓隊2010 小Z的襪子 莫隊演算法

作為乙個生活散漫的人,小z每天早上都要耗費很久從一堆五顏六色的襪子中找出一雙來穿。終於有一天,小z再也無法忍受這惱人的找襪子過程,於是他決定聽天由命 具體來說,小z把這n只襪子從1到n編號,然後從編號l到r l 儘管小z並不在意兩隻襪子是不是完整的一雙,甚至不在意兩隻襪子是否一左一右,他卻很在意襪子...

2038 國家集訓隊 小Z的襪子 莫隊

作為乙個生活散漫的人,小z每天早上都要耗費很久從一堆五顏六色的襪子中找出一雙來穿。終於有一天,小z再也無法忍受這惱人的找襪子過程,於是他決定聽天由命 具體來說,小z把這n只襪子從1到n編號,然後從編號l到r l 儘管小z並不在意兩隻襪子是不是完整的一雙,甚至不在意兩隻襪子是否一左一右,他卻很在意襪子...

洛谷P1494 國家集訓隊 小Z的襪子(莫隊)

從總的襪子數中任意選取 2 個作為分母,再從任意顏色相同的襪子數中選取 2 個,可以先與處理一下雖然資料量不大,但是預處理的時候會爆 int 累加答案的時候也會爆,所以採用 long long const int n 5e4 5 int i,j,k int n,m,t int a n int num...