[BZOJ2038]:[2009ナショナルチーム]小さなZソックス(ホース)(オフラインのMoチーム)

トピックポータル


タイトル説明

人々の規律の人生として、小型の$ Z $はカラフルな靴下の山から見つけるために1ペアを着用するのに長い時間のために午前中に一日を過ごす必要があります。最後に1日、......小さなZはもはや靴下を見つけるために、この迷惑なプロセスを容認することはできませんので、彼は辞任を決めた
$ 1から$ N $の数字から、数字から具体的には、この小さなの$ Z $の$の$ N $の靴下$ L $と$ R $($ L $小さく、2 $ Z $は、靴下の完全なペアではありません気にしませんが、2つの靴下着用、でもどちらかの側ならば、彼は結局、靴下の色について非常に懸念している気にしません二つの異なる色の靴下は)非常に恥ずかしいとなります。
あなたの仕事は、彼が2色の靴下の同じ確率を取得することができますどのくらいの、小さな$のZ $を伝えることです。もちろん、彼は順番に以上$(L、R)$を求めることができるように、できるだけ高く、この確率は、彼らの選択を容易にすることを小さな$ Zは$希望。


入力形式

入力ファイルの最初の行は、2つの正の整数$ N $と$ M $が含まれています。
$ N $は、靴下の数で、$ M $は、問い合わせに記載された小型の$ Z $の数です。
次の行は$ N $ $ $ C_I正の整数を含む、請求項C_I $ $ $ I $は、靴下の色、同じ数字で表さ同じ色を表します。
次$ Mの$線、各2つの正の整数$ L $、$ R $は、クエリを表します。


出力フォーマット

$ Mは$ライン含む、各クエリ出力スコア$ Aについて/ B問い合わせ区間[L、R]の行に$ランダムに選択された二靴下同色確率から表さ$ $。

確率は$ 0 $ 0 $出力/ $ 1であれば、そうでない場合は$のA / B $の出力は、最も簡単な分数でなければなりません。(サンプルを参照してください)


サンプル

サンプル入力

6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6

サンプル出力

2/5
0/1
1/1
4/15


データ範囲とヒント

サンプルは説明しました:

問い合わせ1:2 $ 3 $を抽出することができる$ 1 $ 2つの$ 2 $を抽出する$ 3可能$、$ \ FRAC {1 + 3}の確率有し合計$ C_5 ^ 2 = 10 $可能、 {10} = \ FRAC {4} {10 } = 2/5 $。
お問い合わせ2:合計$ C_3 ^ 2 = 3と同じ色の靴下確率の$ \のFRACを取得することができない可能$、{0} {3 } = 0/1 $。
問い合わせ3:合計$ C_3 ^ 2 = 3 $可能、二つ、$ 3 $に描かれている確率の$ \のFRAC {3} {3 } = 1/1 $。
注意:$ C_A ^ bは$上記の組み合わせの数、$ C_A ^ bは$の$ bは$ $ $異なる物品の選択方式の選択と同等である組み合わせの数を表します。

データ規模と規則:

データの30%、$ N、Mの\ leqslant 5,000 $、
データの60%、$ N、Mの\ leqslant 25,000 $、
データの100%、$ N、M、\ 50,000 leqslant $、$ 1 \ leqslant Lを< R \ leqslantのNの$、$ C_I \ leqslantのNの$。


問題の解決策

提供$ k個$間隔が異なる色を有する、各色$ S [i]は$、答えは:$ \和\ limits_ {i = 1} {K} \ FRAC {C_ {S_I} ^ 2} {C_N ^ 2} $。

最後にバレルを開くのに長いメンテナンスの$、S_I ^ 2 $の発見後に簡単に動き回る、それを維持することができるようになります。

どのような上記の式の中で、あなたは答えがあることがわかります:$ \合計\ limits_ {I = 1} {K} \ FRAC {(S_I-1)\回S_I} {(N-1)\ n倍} $ 、ようにコードを達成するのは非常に簡単です。


コードの時間

#include<bits/stdc++.h>
using namespace std;
struct rec
{
	int l;
	int r;
	int id;
	int pos;
}q[50001];
int n,m;
int a[50001];
int cnt[50001];
long long ans;
long long a1[50001],a2[50001];
bool cmp(rec a,rec b){return a.pos==b.pos?a.r<b.r:a.pos<b.pos;}
void upd(int x,int w)//计算答案
{
	ans-=cnt[a[x]]*cnt[a[x]];
	cnt[a[x]]+=w;
	ans+=cnt[a[x]]*cnt[a[x]];
}
int main()
{
	scanf("%d%d",&n,&m);
	int t=sqrt(n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
	{
		scanf関数( "%d個の%のD"、&Q [i]は.L&Q [I] .R)。
		Q [i]はiは= .ID。
		Q [i]は.POS =(Q [i]が.L-1)/ T + 1。
	} 
	ソート(Q + 1、Q + M + 1、CMP)。
	INT 1 = 1、R = 0。
	以下のために(INT I = 1; I <= M; ++ I)
	{ 
		一方(L <Q [i]が.L)UPD(L ++、 - 1)。
		一方、(L> Q [i]は.L)UPD( - L、1); 
		一方、(R <Q [i]は.R)UPD(++ R、1); 
		一方、(R> Q [i]は.R)UPD(R - 、 - 1)。
		(L == R)なら、{A1 [I] = 0、A2 [I] = 1;} 
		長い長X = ans-(R-L + 1); //分子
		長い長Y =(長い長い)(Q [I] .rq [I] .L + 1)*(Q [i]は.rq [I] .L); //分母
		長い長G = __ GCD(X、Y); //约分
		A1 [Q [ I] .ID] = X / G、A 2 [Q [i]は.ID] = Y / G。
	} 
	ため(; I <= M I ++はi = 1からINT)
		COUT << A1 [I] << '/' << A2 [I] << ENDL。
	0を返します。
}

RP ++

おすすめ

転載: www.cnblogs.com/wzc521/p/11240851.html