小Z的袜子——分块,普通莫队

题目引入
https://ac.nowcoder.com/acm/contest/1034/C
思路:
我们要查询的区间范围为[l,r],设这个区间的长度为n,假设袜子是选取完后,又放回的,也就是说一只袜子可以选取两次,那么表示概率的分母就可以表示为:nn,设这个区间里这种颜色的袜子的总数为sum,选取到这只袜子的概率就为sumsum/n*n。

当然这不符合题目所要求的,但是我们可以用这种比较简单的方法,先求出可放回的概率,再对分子分母进行操作。

用分子减去区间的总长度,是不是就是减去了自身选取自身的概率:sumsum-n,分母变成n(n-1)就是题目所要求的概率了。

基本莫队:
小Z的袜子——分块,普通莫队_第1张图片小Z的袜子——分块,普通莫队_第2张图片
注意:
块值相等的按照right的大小来排序,块值不相等的按照left大小来排序。

ll cmp(KNIGHT a,KNIGHT b){
	if(block[a.left]==block[b.left])
		return a.right<b.right;
	return a.left<b.left;
}

代码:

#include 
#define MAXN 50005
#define ll long long
using namespace std;
struct KNIGHT{
	ll left;
	ll right;
	ll id;
}p[MAXN];
ll c[MAXN],block[MAXN],sum[MAXN];
ll ansa[MAXN],ansb[MAXN];
ll gcd(ll x,ll y){
	if(y!=0)
		return gcd(y,x%y);
	return x;
}
ll cmp(KNIGHT a,KNIGHT b){
	if(block[a.left]==block[b.left])
		return a.right<b.right;
	return a.left<b.left;
}
int main(){
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF){
		int radical = sqrt(n);
		for(int i=1;i<=n;i++){
			scanf("%lld",&c[i]);
			block[i] = (i-1)/radical+1;  
		}
		for(int i=1;i<=m;i++){
			scanf("%lld%lld",&p[i].left,&p[i].right);
			p[i].id = i;
		}
		ll left = 1,right = 0;
		sort(p+1,p+m+1,cmp);
		ll temp = 0 ;
		for(int i=1;i<=m;i++){
			while(left<p[i].left){
				temp -= sum[c[left]]*sum[c[left]];
				sum[c[left]]--;
				temp += sum[c[left]]*sum[c[left]];
				left++;
			}
			while(left>p[i].left){
				left--;
				temp -= sum[c[left]]*sum[c[left]];
				sum[c[left]]++;
				temp += sum[c[left]]*sum[c[left]];
			}
			while(right>p[i].right){
				temp -= sum[c[right]]*sum[c[right]];
				sum[c[right]]--;
				temp += sum[c[right]]*sum[c[right]];
				right--;
			}
			while(right<p[i].right){
				right++;
				temp -= sum[c[right]]*sum[c[right]];
				sum[c[right]]++;
				temp += sum[c[right]]*sum[c[right]];
			}
			ll a = temp - (p[i].right-p[i].left+1);
			ll b = (p[i].right-p[i].left+1)*(p[i].right-p[i].left);
			ll tep = gcd(a,b);
			ansa[p[i].id] = a/tep;
			ansb[p[i].id] = b/tep;
		}
		for(int i=1;i<=m;i++){
			printf("%lld/%lld\n",ansa[i],ansb[i]);
		}
	}
}

你可能感兴趣的:(数据结构——分块)