作为一个生活散漫的人,小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必须为最简分数。(详见样例)
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:共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。
终于入门莫队算法了!!!好开心,但是还有另外两种(在线修改+树上),到时我再弄一弄。目前的莫队已经足够我使用了。
提供两种方法:但是莫队的模板是不变的,但是add( ) ,del ( ) 这个要自己写。
网上的这个是用公式来表示每一种颜色的袜子的抽到的次数,综合每一种颜色 / 所有情况
在这里写一遍吧:
在一段区域内,有多种颜色,每一种颜色出现的次数为:a,b,c,……x次
对于(a+b+c……x)相当于整个区间的
只需要用莫队来维护 a^2 平方数即可。
网上的答案:就是把原来的挖出来-=num[x]*num[x],然后num[x]++,再填上去+=num[x]*num[x]
我的想法:每次添加和之前的比较:(a+1)=a^2+2a+1 ,添加时只要进行+=2a+1 / -= (2a-1)即可
#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
template
void read(T &x){
T f=1;char c=getchar();
for( ; !isdigit(c) ; c=getchar()){ if(f=='-') f=-1; }
for( ; isdigit(c) ; c=getchar()){ x=x*10+c-'0';}
}
int n,m,a[N],num[N],unit;
ll tmp;
typedef struct node{
int L,R,No;
bool operator < (const node &p)const {
return L/unit!=p.L/unit ? L/unit < p.L/unit : RQ[i].R) { del(a[(R--)]); }
while(LQ[i].L) { add(a[(--L)]); }
ans[Q[i].No]=F(i);
}
for(int i=1;i<=m;i++){
printf("%lld/%lld\n",ans[i].F1,ans[i].F2);
}
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=1;i<=m;i++){
read(Q[i].L),read(Q[i].R),Q[i].No=i;
}
solve();
return 0;
}
/*
6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6
*/
这个是我看着示例推出来的,因为每一次添加一种之前在序列中已有的颜色,
不就是对已有的颜色构建关系吗?那么我只要维护整个分子即可。
add( ): 加上序列中出现过的次数, 次数+1。
del ( ) :次数-1 ,减去序列中出现过的次数。
分母就是组合数即可。
#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
template
void read(T &x){
T f=1;char c=getchar();
for( ; !isdigit(c) ; c=getchar()){ if(f=='-') f=-1; }
for( ; isdigit(c) ; c=getchar()){ x=x*10+c-'0';}
}
int n,m,a[N],num[N],unit;
ll tmp;
typedef struct node{
int L,R,No;
bool operator < (const node &p)const {
return L/unit!=p.L/unit ? L/unit < p.L/unit : RQ[i].R) { del(a[(R--)]); }
while(LQ[i].L) { add(a[(--L)]); }
ans[Q[i].No]=F(i);
}
for(int i=1;i<=m;i++){
printf("%lld/%lld\n",ans[i].F1,ans[i].F2);
}
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=1;i<=m;i++){
read(Q[i].L),read(Q[i].R),Q[i].No=i;
}
solve();
return 0;
}
/*
6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6
*/
还有其他题:
牛客第八场 F
牛客第九场 F
牛客第十场 E
HDU 某一场的莫队
codeforces 375D Tree and Queries 题解
codeforces 86D power array题解
hdu 4638 Group 题解