莫队算法----区间求和
时间:2019-09-17
本文章向大家介绍莫队算法----区间求和,主要包括莫队算法----区间求和使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
连接 https://ac.nowcoder.com/acm/contest/1085/G
链接:https://ac.nowcoder.com/acm/contest/1085/G
来源:牛客网
题目描述
小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个数,每个数为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
输出
复制15 14 6 73 29
题目大意:在制定的一段区间内求arr[i]*cnt[arr[i]]之和,即一段区间内某一个数乘以该数字出现的次数。
莫队算法 一篇讲的很好的博客 https://www.cnblogs.com/WAMonster/p/10118934.html
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll ans=0; const int N=1E5+7; ll arr[N],cnt[N]; ll base; ll a[N]; struct stu{ ll l,r,k,id; bool friend operator < (const stu &x,const stu &y){ if(x.k!=y.k) return x.l<y.l; return x.r<y.r; } }node[N]; void add(int x){ ans+=(2*cnt[arr[x]]+1) *arr[x]; cnt[arr[x]]++; } void del(int x){ ans-=(2*cnt[arr[x]]-1) *arr[x]; cnt[arr[x]]--; } int main(){ int n,m; cin>>n>>m; base=sqrt(n); for(int i=1;i<=n;i++) scanf("%lld",&arr[i]); for(int i=1;i<=m;i++){ ll l,r; scanf("%lld%lld",&l,&r); node[i].id=i; node[i].l=l; node[i].r=r; node[i].k=l/base; } ll l=1,r=0; sort(node+1,node+1+m); for(int i=1;i<=m;i++){ int ql=node[i].l,qr=node[i].r; while(l<ql) del(l++); while(l>ql) add(--l); while(r>qr) del(r--); while(r<qr) add(++r); a[node[i].id]=ans; } for(int i=1;i<=m;i++) printf("%lld\n",a[i]); return 0; }
疑问1:为什么加数的时候是++r和--l而删除的时候却是l++或者r--?
因为我们规定,区间边界也会记录在内,因此当del的时候是先删除当前值,在自增或者自减,而add的时候我们是对下一个数的操作,因此要先自增或者自减再操作,这样才能保证增加的时候把最后边界加上,减少的时候不把边界减去;
疑问2:为什么ans+/-=(2*cnt[arr[x]]+/-1)*arr[x];?
cnt[arr[x]]是数arr[x]当前的数量,arr[x]*cnt[arr[x]]是对之前的cnt[arr[x]]个arr[x]每一个在加上个arr[x], 又新增的一个arr[x],因此要再加上arr[x]*(cnt[arr[x]]+1),最终结果就是(2*cnt[arr[x]]+/-1)*arr[x]
减少的时候应该是减去arr[x]*(cnt[arr[x]]-1)+arr[x]*cnt[arr[x]];
原文地址:https://www.cnblogs.com/Accepting/p/11533600.html
- Linux64位程序移植
- history命令使用方法详解
- Linux删除乱码文件的方法
- 和智能机器一起工作,而不是惧怕它们
- Hulu大数据架构与应用经验
- SQL Server 2005:一个使用新创建的User的问题和解决方法
- Audit Logging-Stored Procedure
- Linux进程间通信(四) - 共享内存
- 扩展UltraGrid控件实现对所有数据行的全选功能[Source Code下载]
- Linux进程间通信(一) - 管道
- Linux进程间通信(二) - 消息队列
- Linux进程间通信(三) - 信号
- 我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
- Linux进程间通信(IPC)机制总览
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- centos7系统下python2与python3共存
- linux把一个文件的内容复制到另一个文件的末尾
- 详解linux下nohup日志输出过大问题解决方案
- K8S dashboard 2.0 安装配置并使用 ingress-nginx 访问
- linux模糊查找文件用什么命令比较好
- Ubuntu14.04服务器环境下配置PHP7.0+Apache2+Mysql5.7的方法
- Linux C 后台服务程序单进程控制的实现
- Linux下SSH免密码登录配置详解
- SSH端口转发实现内网穿透的实现
- 在linux中用同一个版本的R 同时安装 Seurat2 和 Seurat3的教程
- AUCell:在单细胞转录组中识别细胞对“基因集”的响应
- linux查看硬件配置命令的方法示例
- Ubuntu环境编译安装PHP和Nginx的方法
- Ubuntu环境源码编译安装xdebug的方法
- CNS图表复现07—原来这篇文章有两个单细胞表达矩阵