牛客小白月赛17-G区间求和(莫队)

牛客小白月赛17-G区间求和(莫队)

题目链接:https://ac.nowcoder.com/acm/contest/1085/G

题意: 给你n个数,每个数为$a_i$​,现在有m个询问,每个询问l,r,需要求出:

∑ i = l r a i ∗ n u m ( a [ i ] ) \sum_{i=l}^{r}a_i*num(a[i]) i=lrainum(a[i])

n u m ( a [ i ] ) num(a[i]) num(a[i]) a i a_i ai在这个区间中出现的次数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;

int n,m,b[N];
ll ans[N],cnt[N],res; 
struct node{
	int l,r,id,pos;
	bool operator < (const node &b)const {
		if(pos==b.pos)return r<b.r;
		else return pos<b.pos;
	}
}a[N];

void add(int x)
{
	res-=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
	cnt[b[x]]++;
	res+=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
}

void del(int x)
{
	res-=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
	cnt[b[x]]--;
	res+=1ll*b[x]*cnt[b[x]]*cnt[b[x]];
}

int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	int block=sqrt(n);
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=m;i++){
		cin>>a[i].l>>a[i].r;
		a[i].id=i;
		a[i].pos=a[i].l/block;
	}
	sort(a+1,a+1+m);
	int l=a[1].l,r=a[1].l-1;
	for(int i=1;i<=m;i++){
		while(l<a[i].l)del(l++);
		while(l>a[i].l)add(--l);
		while(r<a[i].r)add(++r);
		while(r>a[i].r)del(r--);
		ans[a[i].id]=res;
	}
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值