AcWing 802. 区间和 离散化

2024-02-13 11:44
文章标签 acwing 区间 离散 802

本文主要是介绍AcWing 802. 区间和 离散化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 题目链接
  • 题目描述
  • 解题思路
  • 代码实现
  • 总结


题目链接

链接: AcWing 802. 区间和

题目描述

在这里插入图片描述

解题思路

离散化是一种常用的技巧,它能够将原始的连续数值转换为一组离散的值,从而简化问题的处理。在这段代码中,离散化的过程主要分为三个步骤。

第一步是将需要进行离散化的数值(在这里是add数组和query数组中的x、l、r值)存储到一个数组中(这里是alls数组)。这一步是为了之后的去重和排序做准备。

第二步是对存储了所有待离散化数值的数组进行去重和排序操作。通过这一步,我们得到了一个不重复且有序的离散化数组,能够完整地覆盖所有需要处理的数值。

第三步是使用离散化后的数值进行替换和处理。在这段代码中,对add数组中的操作和query数组中的查询都是通过离散化后的位置来进行处理的,而不再直接使用原始的连续数值。这样做的好处是,在处理过程中不再受到原始数值的大小和分布的影响,简化了问题的处理过程。

离散化核心代码

 //离散化sort(alls.begin(),alls.end());alls.erase(unique(alls.begin(),alls.end()),alls.end());

代码实现

#include<iostream>
#include <vector>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
const int N=3e6+10;
int n,m;
int a[N],s[N];
vector<int> alls;//存储坐标
vector<PII> add,query;//读入操作和求值操作
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可以不考虑边界问题
}
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());//处理读入for(auto item:add){int x=find(item.first);a[x]+=item.second;}for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];for(auto item:query){int l=find(item.first),r=find(item.second);cout<<s[r]-s[l-1]<<endl;}return 0;
}

总结

存储数值:将需要离散化的数值存储到一个数组中,如add和query数组中的x、l、r值都存储在alls数组中。

去重和排序:对存储了所有待离散化数值的数组进行去重和排序操作,得到一个不重复且有序的离散化数组。

替换和处理:使用离散化后的数值进行替换和处理。在这段代码中,操作和查询都是通过离散化后的位置来进行处理的,简化了问题的处理过程。

离散化的目的是将连续的数值转换为离散的数值,从而简化问题的处理。通过离散化,可以减少对原始数值大小和分布的敏感性,使问题的处理更加简单和高效。

这篇关于AcWing 802. 区间和 离散化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705443

相关文章

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu4267区间统计

题意:给一些数,有两种操作,一种是在[a,b] 区间内,对(i - a)% k == 0 的加value,另一种操作是询问某个位置的值。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import

hdu4417区间统计

给你一个数列{An},然后有m次查询,每次查询一段区间 [l,r] <= h 的值的个数。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamRead

hdu3333区间统计

题目大意:求一个区间内不重复数字的和,例如1 1 1 3,区间[1,4]的和为4。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

【AcWing】851. 求最短路

spfa算法其实是对贝尔曼福特算法做一个优化。 贝尔曼福特算法会遍历所有边来更新,但是每一次迭代的话我不一定每条边都会更新,SPFA是对这个做优化。 如果说dist[b]在当前这次迭代想变小的话,那么一定是dist[a]变小了,只有a变小了,a的后继(b)才会变小。 用宽搜来做优化,用一个队列,队列里边存的就是所有变小了的结点(队列里存的是待更新的点)。 基本思路就是我更新过谁,我再拿

【uva】11536-Smallest Sub-Array(区间移动问题)

一个区间移动的问题,1A了,感觉没什么好说的。。 13975926 11536 Smallest Sub-Array Accepted C++ 0.809 2014-08-01 11:00:20 #include<cstdio>#include<cstring>#include<iostream>using namespace std;#define INF 1 << 30

【hdu】Just a Hook(线段树区间修改)

线段树模板题,练的是懒惰标记。 懒惰标记,就是更新一段区间的时候,如果小区间被包含在了所需要更新的区间里面,那么直接对代表这个区间的数组元素赋值,之后做一个标记(表示这个区间的子区间都需要更新)但是不继续递归(这样可以节省很多的时候)。 116571152014-09-15 14:17:26Accepted1698796MS2380K1750 BG++KinderRiven #

【hdu】I Hate It(线段树,结点修改求区间最大值)

线段树的模板题,还是二分递归。 #include <iostream>#include <cstdlib>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <set>#include <map>#incl

【hdu】敌兵布阵(线段树,更加结点,区间求和)

最近开始刷线段树,主要围绕notonlysuccess的线段树总结刷。 结点修改还是比较简单的,不需要什么懒惰标记,直接二分递归就可以了。 #include <iostream>#include <cstdlib>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vecto

ZOJ 3324 Machine(线段树区间合并)

这道题网上很多代码是错误的,由于后台数据水,他们可以AC。 比如这组数据 10 3 p 0 9 r 0 5 r 6 9 输出应该是 0 1 1 所以有的人直接记录该区间是否被覆盖过的方法是错误的 正确方法应该是记录这段区间的最小高度(就是最接近初始位置的高度),和最小高度对应的最长左区间和右区间 开一个sum记录这段区间最小高度的块数,min_v 记录该区间最小高度 cover