洛谷 P1494 [国家集训队]小Z的袜子 题解

28 篇文章 0 订阅
3 篇文章 0 订阅

洛谷 P1494 [国家集训队]小Z的袜子 题解

题目:在

考虑贡献。

一段区间是 ( l , r ) (l,r) (l,r),那么总选择数是 C r − l + 1 2 C^2_{r-l+1} Crl+12

设有 k k k个不同颜色,第 i i i个有 a i a_i ai次,那么这一个的贡献是 C a i 2 C_{a_i}^2 Cai2

所以答案为 ∑ C a i 2 C r − l + 1 2 \frac {\sum C_{a_i}^2}{C_{r-l+1}^2} Crl+12Cai2

莫队维护 C a i 2 C_{a_i}^2 Cai2

具体,假设某种颜色原有 x x x次。多了一次,答案就多加了 x x x,因为这个新的要与原来的 x x x个匹配。现有 x x x次,少了一次,答案就要减去 x x x,因为原来的那个与剩下的都匹配了,要反悔。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,q,m,a[50005],cnt[50005],ans[50005][3],sum;
struct query{
	ll x,l,r;
}b[50005];
bool cmp(query c,query d){
	return c.l/m!=d.l/m?c.l<d.l:((c.l/m)&1?c.r<d.r:c.r>d.r);
} 
void add(ll x){
	sum+=cnt[a[x]];
	cnt[a[x]]++;
}
void del(ll x){
	cnt[a[x]]--;
	sum-=cnt[a[x]];
}
ll C(ll x){
	return x*(x-1)/2;
}
int main(){ 
	scanf("%lld%lld",&n,&q);
	m=sqrt(n);
	for (ll i=1;i<=n;i++) scanf("%lld",&a[i]);
	for (ll i=1;i<=q;i++) scanf("%lld%lld",&b[i].l,&b[i].r),b[i].x=i;
	sort(b+1,b+q+1,cmp);
	ll le=1,ri=0;
	for (ll i=1,l,r;i<=q;i++){
		l=b[i].l,r=b[i].r;
		while (le<l) del(le),le++;
		while (ri>r) del(ri),ri--;
		while (le>l) le--,add(le);
		while (ri<r) ri++,add(ri);
		ans[b[i].x][0]=sum;
		ans[b[i].x][1]=C(r-l+1);
	}
	for (ll i=1;i<=q;i++){
		if (ans[i][1]==0){
			printf("0/1\n");
			continue;
		}
		ll g=__gcd(ans[i][0],ans[i][1]);
		if (g)ans[i][0]/=g;
		if (g)ans[i][1]/=g;
		printf("%lld/",ans[i][0]);
		printf("%lld\n",ans[i][1]);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值