链接:https://ac.nowcoder.com/acm/contest/1085/G
来源:牛客网
区间求和
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld题目描述
小sun最近突然对区间来了兴趣,现在他有这样一个问题想问问你:
给你n个数,每个数为aia_iai,现在有m个询问,每个询问l,r,需要求出:
∑i=lrai∗num(ai)\sum_{i=l}^r a_i*num(a_i)∑i=lrai∗num(ai)
num(ai)num(a_i)num(ai)代表aia_iai在这个区间中出现的次数。
你能帮帮他吗?输入描述:
第一行,两个整数n,m 第二行,总共n个数,代表这个数列 接下来m行,每行两个整数l,r,代表一个询问
输出描述:
输出总共m行,对于每个询问,输出这个询问对应的答案
示例1
输入
复制
10 5 1 3 2 4 5 6 4 5 6 7 1 5 2 5 3 4 1 10 3 7
输出
复制
15 14 6 73 29
备注:
1≤n,m≤1e51\leq n,m\leq 1e51≤n,m≤1e5 1≤ai≤1e51\leq a_i\leq 1e51≤ai≤1e5 1≤l,r≤n1\leq l,r\leq n1≤l,r≤n
》》》莫队算法
题解:莫队例题 套模板 (最后输出为%lld类型!!)
分块: return (l/block==S.l/block) ? r<S.r:l<S.l;
#include<bits/stdc++.h> #define ll long long using namespace std; ll c[100005]; ll num[100005]; ll block; ll n,m; ll ans=0; ll anss[100005]; struct node { int l,r,id; bool operator < (const node & S) const { return (l/block==S.l/block) ? r<S.r:l<S.l; //同块排序 } }a[100005]; int add(int v) { ans-=1ll*c[v]*num[c[v]]*num[c[v]];//!!! num[c[v]]++; ans+=1ll*c[v]*num[c[v]]*num[c[v]];//!!! } int del(int v) { ans-=1ll*c[v]*num[c[v]]*num[c[v]];//!!! 先减后加 num[c[v]]--; ans+=1ll*c[v]*num[c[v]]*num[c[v]];//!!! } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&c[i]); } for(int i=1;i<=m;i++) { scanf("%d%d",&a[i].l,&a[i].r); a[i].id=i; } block=sqrt(n); sort(a+1,a+1+m); int l=0,r=0; for(int i=1;i<=m;i++) { int ql=a[i].l; int qr=a[i].r; while(ql<l) add(--l); while(r<qr) add(++r); while(l<ql) del(l++);//!!前置和后置 while(qr<r) del(r--);//!! anss[a[i].id]=ans; } for(int i=1;i<=m;i++) printf("%lld\n",anss[i]); //最后输出类型为%lld!!!! }
区间求和 (莫队算法 、分块排序)
最新推荐文章于 2024-08-21 13:46:44 发布