【离散化】离散化
definition
对于一些数量较少但是数值较大或出现负数但难以处理的数据,如果只需要考虑他们的大小关系,可以给他们重新赋值。一般的,对于个数据,可以将他们重新赋值为之间的数字。这种方法叫做离散化。
Solution
先介绍三个。
:对于一个有序数列,将之去重。一般的,若长度为的升序序列中有个互不相同的元素,那么经过去重的数列前个值是这个值按照升序排序,剩下的位置为乱序。降序排列同理。的调用方法是其中和位置为序列首元素的迭代器以及序列尾元素的迭代器.即区间左闭右开。函数是一个有返回值的函数,其返回值是去重后最后一个有序元素的迭代器。即返回一个左闭右开区间的右端点。
:对于一个单调不下降数列,返回一个迭代器,迭代器的位置是第一个大于等于某个值的数。其调用方式是,其中是键值。迭代器的位置就是大于等于v的第一个位置。
__:调用方法等同理。不同的是此函数返回的是一个严格大于值的最小位置。
不要问我为什么要现学这些东西因为我以前不怎么用STL
然后,使用一个temp数组记录原数组的值。对temp数组排序去重,那么原数组第i个位置的值就是temp去重后大于等于原数组原值的位置的值。好绕啊怎么办,还是看代码吧
int MU[maxn],temp[maxn];
qr(n);
for(rg int i=1;i<=n;++i) {
qr(MU[i]);temp[i]=MU[i];
}
std::sort(temp+1,temp+1+n);
rg int cnt=std::unique(temp+1,temp+1+n)-temp-1;
for(rg int i=1;i<=n;++i) MU[i]=std::lower_bound(temp+1,temp+cnt+1,MU[i])-temp;
Example
Description
小f遇到一扇门
小F发现门上有着n个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小次数。但小FF不会……只好又找到了你,并答应事成之后与你三七分……
Input
第一行为一个整数n,表示序列长度
第二行为n个整数,表示序列A中每个元素。
Output
一个整数ans,即最少操作次数。
Sample Input
4
2 8 0 3
Sample Output
3
Hint
;
。
Solution
根据火柴排队那道题的经验,我们可以得到每次交换相邻元素将一个乱序序列变成单调不下降的步数就是序列中逆序对数。于是使用树状数组求逆序对。因为下标不能为负,所以考虑离散化。
Code
#include<cstdio>
#include<algorithm>
#define rg register
#define ci const int
#define cl const long long int
typedef long long int ll;
namespace IO {
char buf[90];
}
template<typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while(ch>'9'||ch<'0') lst=ch,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst=='-') x=-x;
}
template<typename T>
inline void write(T x,const char aft,const bool pt) {
if(x<0) x=-x,putchar('-');
int top=0;
do {
IO::buf[++top]=x%10+'0';
x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}
template<typename T>
inline T mmax(const T a,const T b) {if(a>b) return a;return b;}
template<typename T>
inline T mmin(const T a,const T b) {if(a<b) return a;return b;}
template<typename T>
inline T mabs(const T a) {if(a<0) return -a;return a;}
template<typename T>
inline void mswap(T &a,T &b) {
T temp=a;a=b;b=temp;
}
const int maxn = 500010;
int n;
int MU[maxn],temp[maxn],frog[maxn];
ll ans;
inline int lowbit(ci x) {return x&((~x)+1);}
int ask(int);
void add(int);
int main() {
qr(n);
for(rg int i=1;i<=n;++i) {
qr(MU[i]);temp[i]=MU[i];
}
std::sort(temp+1,temp+1+n);
rg int cnt=std::unique(temp+1,temp+1+n)-temp-1;
for(rg int i=1;i<=n;++i) MU[i]=std::lower_bound(temp+1,temp+cnt+1,MU[i])-temp;
for(rg int i=1;i<=n;++i) {
ans+=ask(n)-ask(MU[i]);
add(MU[i]);
}
write(ans,'\n',true);
return 0;
}
int ask(int x) {
int _ans=0;
while(x) {
_ans+=frog[x];
x-=lowbit(x);
}
return _ans;
}
void add(int x) {
while(x <= n) {
++frog[x];
x+=lowbit(x);
}
}
Summary
:返回序列中第一个大于等于键值的数。
:返回序列中第一个严格大于键值的数。
区分并掌握
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具