bzoj2038 小Z的袜子 【莫队】

版权声明:----------------------------------------转载是ok的,但要附上出处哟 https://blog.csdn.net/qq_43040655/article/details/87527631

思路:
裸的莫队,注意有一点小的组合数学的知识

#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define int long long
const int maxn=5e4+10;
int col[maxn],amt[maxn],b[maxn],n,m,k,c[maxn][5];
typedef pair<int,int> T;
T ret[maxn];
struct pi{
	int l,r,id;
	bool operator <(const pi &t) const{
		return (b[l]<b[t.l]||(b[l]==b[t.l])&&r<t.r);
	}
}p[maxn];
inline void pre(){
	c[0][0]=1;
	for(int i=1;i<=n;++i){
		c[i][0]=1;
		for(int j=1;j<=2;++j){
			c[i][j]=c[i-1][j-1]+c[i-1][j];
		}
	}
}
inline int gcd(int a,int b){
	int c;
	while(b){
		c=b;b=a%b;a=c;
	}
	return a;
}


signed main(){
	sf("%lld%lld",&n,&m);k=sqrt(n);
	pre();
	for(int i=1;i<=n;++i)sf("%lld",&col[i]),b[i]=(i-1)/k+1;
	for(int i=1;i<=m;++i)sf("%lld%lld",&p[i].l,&p[i].r),p[i].id=i;
	sort(p+1,p+m+1);
	int l=0,r=0,up=0,down=0;amt[0]=1;
	for(int i=1;i<=m;++i){
		while(r<p[i].r){
			++r;++amt[col[r]];
			up+=c[amt[col[r]]-1][1];
		}
		while(l<p[i].l){
			--amt[col[l]];
			up-=c[amt[col[l]]][1];
			++l;
		}
		while(l>p[i].l){
			--l;++amt[col[l]];
			up+=c[amt[col[l]]-1][1];
		}
		while(r>p[i].r){
			--amt[col[r]];
			up-=c[amt[col[r]]][1];
			--r;
		}
		if(up==0)ret[p[i].id]=make_pair(0,1);
		else{
			down=c[(r-l+1)][2];int q=gcd(down,up);
			ret[p[i].id]=make_pair(up/q,down/q);
		}
	}
	for(int i=1;i<=m;++i)printf("%lld/%lld\n",ret[i].first,ret[i].second);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43040655/article/details/87527631