首页 > 其他分享 >AcWing 802. 区间和

AcWing 802. 区间和

时间:2023-12-07 20:24:29浏览次数:33  
标签:end int mid back push alls 区间 802 AcWing

题面:
假定有一个无限长的数轴,数轴上每个坐标上的数都是 \(0\) 。
现在,我们首先进行 \(n\) 次操作,每次操作将某一位置 \(x\) 上的数加 \(c\) 。
接下来,进行 \(m\) 次询问,每个询问包含两个整数 \(l\) 和 \(r\) ,求出在区间 \([l,r]\) 之间的所有数的和。

原题链接:802. 区间和 - AcWing

保序离散化

离散化就是把大而分散的一段段使用到的稀疏区间,整合映射到连续的一段较小的稠密区间里,然后就可以通过普通前缀和公式来计算连续一段的区间和,本质上就是化大为小,把稀疏离散化简为稠密连续的一段。—— acvv_motibodo

建立键值对(离散化模板)

去重:原数组中可能拥有重复元素

//使用库函数快速去重
vector<int> alls;				//存储所有待离散化的值
sort(alls.begin(), alls.end());	//排序
//去重:unique负责去重并返回数组尾端点,erase负责释放多余空间
alls.erase(unique(alls.begin(), alls.end()), alls.end());

求值:二分求出键值化后的值

//找到第一个大于等于x的位置
int find(int x) {
	int l = 0, r = alls.size() - 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (alls[mid] >= x)	r = mid;
		else l = mid + 1;
	}
	return r + 1;	//映射到1,2,...n
}

解题思路

迄今为止看到思路最清晰的图解之一,来自liangshang大佬,搬运仅作学习,非常感谢:
image

代码

#include<bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
const int N = 3e5 + 10;     //1e5会报SE

int n, m;
int a[N], s[N];

vector<int> alls;	//alls数组中存储的均为坐标(key)
vector<PII> add, query;	//对应两种操作,插入与查询

//找到第一个大于等于x的位置
int find(int x) {
	int l = 0, r = alls.size() - 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (alls[mid] >= x)	r = mid;
		else l = mid + 1;
	}
	return r + 1;	//映射到1,2,...n
}

int main()
{
	cin >> n >> m;
	//存储键值对
	for (int i = 0; i < n; i++) {
		int x, c;
		cin >> x >> c;
		add.push_back({ x,c });
		alls.push_back(x);
	}
	//存储左右端点,一同建立映射
	for (int i = 0; i < m; i++) {
		int l, r;
		cin >> l >> r;
		query.push_back({ l,r });
		alls.push_back(l);
		alls.push_back(r);
	}
	//去重,建立索引
	sort(alls.begin(), alls.end());
	alls.erase(unique(alls.begin(), alls.end()), alls.end());
	//处理插入,未涉及添加操作的端点值为默认0
	for (auto i : add) {
		int x = find(i.first);	//键
		a[x] += i.second;		//值
	}
	//预处理前缀和
	for (int i = 1; i <= alls.size(); i++)
		s[i] = s[i - 1] + a[i];
	//处理查询
	for (auto i : query) {
		int l = find(i.first);
		int r = find(i.second);
		cout << s[r] - s[l - 1] << endl;
	}
}

标签:end,int,mid,back,push,alls,区间,802,AcWing
From: https://www.cnblogs.com/haruhomu/p/17883867.html

相关文章

  • 59AcWing 840. 模拟散列表
    点击查看代码#include<iostream>#include<cstring>usingnamespacestd;constintN=200003,null=0x3f3f3f3f;inth[N];intfind(intx){intk=(x%N+N)%N;//索引while(h[k]!=null&&h[k]!=x){k++;if(k==N)k=0;//重新搜索......
  • Acwing 5367. 不合群数
    题面:如果一个正整数无法被 \([2,a]\) 范围内的任何整数整除,则称其为不合群数。请你计算并输出 \([2,b]\) 范围内的最大不合群数。提示:\(10\) 亿内的最大质数是 \(999999937\),且相邻质数之间的差值均不超过 \(300\)原题链接:5367.不合群数-AcWing根据给出的提示判......
  • AcWing 1205. 买不到的数目
    题面:水果糖被包成\(n\)颗一包和\(m\)颗一包的两种,用这两种包装来组合,不能拆包卖。在\(4\)颗一包和\(7\)颗一包的情况下,最大不能买到的数量是\(17\)。本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。原题链接:1205.买不到的数目-AcWing数论:组合......
  • ACwing342. 道路与航线
    这道题是把拓扑排序和迪杰斯特拉交叉进行。#include<iostream>#include<stdio.h>#include<algorithm>#include<cstring>#include<queue>#include<vector>usingnamespacestd;typedefpair<int,int>PII;constintN=25005,M=50......
  • AcWing 836. 合并集合
    题面:一共有 \(n\) 个数,编号是 \(1∼n\),最开始每个数各自在一个集合中。现在要进行 \(m\) 个操作,操作共有两种:1、Mab,将编号为 \(a\) 和 \(b\) 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略操作;2、Qab,询问编号为 \(a\) 和 \(b\) 的两个数是否在......
  • AcWing 240. 食物链
    题面:有三类动物\(A,B,C\),\(A\)吃\(B\),\(B\)吃\(C\),\(C\)吃\(A\)。现有\(N\)个动物,以\(1∼N\)编号,每个动物都是\(A,B,C\)中的一种。用两种说法对这\(N\)个动物所构成的食物链关系进行描述:第一种说法是1XY,表示\(X\)和\(Y\)是同类。第二种说法是2X......
  • AcWing 148. 合并果子
    题面:把所有的果子合成一堆:每一次合并,可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。达达在合并果子时总共消耗的体力等于每次合并所耗体力之和。假定每个果子重量都为\(1\),并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使达达耗费的体......
  • AcWing 282. 石子合并
    题面:设有 \(N\)堆石子排成一排,其编号为 \(1,2,3,…,N\),现在要将这 \(N\) 堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和。请找出一种合理的方法,使总的代价最小,输出最小代价。原题链接:282.石子合并-AcWing乍一看上去很像哈夫曼树,但并......
  • Acwing 3240. 压缩编码
    本题大意:使用01串为单词编码,要求:1、编码使用前缀码,即任何一个单词的编码不是另一个单词编码的前缀;2、编码需要按字典序升序排列,比如 \(C\) 的编码的字典序需要 \(D\) 的编码之前。请找出一种字典序编码,使得文字经过编码后的长度\(L\)最小,输出最小长度。原题链接:324......
  • AcWing 143. 最大异或对
    题面:在给定的\(N\)个整数\(A1,A2……AN\)中选出两个进行\(xor\)(异或)运算,得到的结果最大是多少?原题链接:143.最大异或对-AcWing什么是异或?1、相同为\(0\),不同为\(1\);2、\(0\)和任意数字进行异或,结果为数字本身。为什么该题采用二叉字典树?整数可以转化为32位......