其他分享
首页 > 其他分享> > luogu P1494 [国家集训队]小Z的袜子

luogu P1494 [国家集训队]小Z的袜子

作者:互联网

题面传送门
其实个人感觉这道题如果能用莫队过评分偏高(如果您是主席树大佬当我没说)
这道题用莫队怎么过呢?
我们可以分析一下式子
我们以aia_iai​代表区间内颜色为iii的袜子有几双,那么答案是i=1nai(ai1)2(rl+1)(rl)2\dfrac{\sum\limits_{i=1}^{n}{\dfrac{a_i*(a_i-1)}{2}}}{\dfrac{(r-l+1)(r-l)}{2}}2(r−l+1)(r−l)​i=1∑n​2ai​∗(ai​−1)​​
拆一下式子,得到i=1nai2(rl1)(rl+1)(rl)\dfrac{\sum\limits_{i=1}^{n}{a_i^2}-(r-l-1)}{(r-l+1)(r-l)}(r−l+1)(r−l)i=1∑n​ai2​−(r−l−1)​
那么这道题变成了求区间内每种颜色的平方和。这可是莫队的板子
怎么解详见这一篇
代码实现:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,m,ans1[200039],ans2[200039],tot,pus,now,k,f[200039],l,r,a[200039],tmp,x,y,z[200039];
struct yyy {
	long long x,y,num;
} s[200039];
inline bool cmp(yyy a,yyy b) {
	return (f[a.x]^f[b.x])?(f[a.x]<f[b.x]):((f[a.x]&1)?a.y<b.y:a.y>b.y);
}
inline void read(long long &x) {
	char s=getchar();int f=1;x=0;
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
	x*=f;
}
int main() {
	register int i,j;
	scanf("%lld%lld",&n,&m);
	k=sqrt(n);
	for(i=1; i<=k; i++) f[i]=1;
	for(i=k+1; i<=n; i++) f[i]=f[i-k]+1;
	for(i=1; i<=n; i++) read(a[i]);
	for(i=1; i<=m; i++) {
		read(x);
		read(y);
		if(x==y) ans2[i]=1;
		else s[++tmp]=(yyy) {x,y,i};
	}
	sort(s+1,s+tmp+1,cmp);
	for(i=s[1].x; i<=s[1].y; i++) {
		tot+=z[a[i]]*2+1;
		z[a[i]]++;
	}
	l=s[1].x;r=s[1].y;
	pus=(s[1].y-s[1].x+1)*(s[1].y-s[1].x);
	now=__gcd(pus,(tot-(s[1].y-s[1].x+1)));
	ans1[s[1].num]=(tot-(s[1].y-s[1].x+1))/now;
	ans2[s[1].num]=pus/now;
	//printf("%lld\n",tot);
	for(i=2; i<=tmp; i++) {
		while(l<s[i].x) tot-=z[a[l]]*2-1,z[a[l]]--,l++;
		while(r>s[i].y) tot-=z[a[r]]*2-1,z[a[r]]--,r--;
		while(l>s[i].x) l--,tot+=z[a[l]]*2+1,z[a[l]]++;
		while(r<s[i].y) r++,tot+=z[a[r]]*2+1,z[a[r]]++;
		//printf("%lld\n",tot);
		if(tot-(s[i].y-s[i].x+1)==0){ans1[s[i].num]=0;ans2[s[i].num]=1;continue;}
		pus=(s[i].y-s[i].x+1)*(s[i].y-s[i].x);
		now=__gcd(pus,tot-(s[i].y-s[i].x+1));
		ans1[s[i].num]=(tot-(s[i].y-s[i].x+1))/now;
		ans2[s[i].num]=pus/now;
	}
	for(i=1;i<=m;i++) printf("%lld/%lld\n",ans1[i],ans2[i]);
}

时间复杂度O((n+m)nlog2n)O((n+m)\sqrt nlog^2n)O((n+m)n​log2n)

标签:P1494,luogu,200039,long,while,tot,dfrac,include,国家集训队
来源: https://blog.csdn.net/fxt275307894a/article/details/104897356