离散化数据
离散化本质上可以看成是一种 哈希,其保证数据在哈希以后仍然保持原来的全/偏序关系。
通俗地讲就是当有些数据因为本身很大或者类型不支持,自身无法作为数组的下标来方便地处理,而影响最终结果的只有元素之间的相对大小关系时,我们可以将原来的数据按照从大到小编号来处理问题,即离散化。
用来离散化的可以是大整数、浮点数、字符串等等。
用数学的定义来讲,两个关联偏序集集合分别为 S 1 S_{1} S1和 S 2 S_{2} S2,且存在一一映射关系。对集合 S 1 S_{1} S1运用变换 T T T,那么 S 2 S_2 S2的偏序集不变。
模板
此题我们需要两次离散化数据,第一次是为了减小数据范围,第二次是转化问题,将最小移动次序转化成逆序对问题。
#include <bits/stdc++.h>
using namespace std;
#define FR freopen("in.txt", "r", stdin)
#define FW freopen("out.txt", "w", stdout)
#define MAXT INT_MAX
#define GET(x) (x.empty() ? LONG_LONG_MIN : x.front())
#define BELONG(x) (!x.empty() && len == x.front())
typedef long long ll;
#define MOD 99999997
int t[100005];
inline int lowbit(int x)
{
return x & -x;
}
void inc(int idx)
{
while (idx < 100005)
{
t[idx]++;
idx += lowbit(idx);
}
}
ll psum(int idx)
{
ll ans = 0;
while (idx > 0)
{
ans = (ans + t[idx]) % 99999997;
idx -= lowbit(idx);
}
return ans;
}
struct Node
{
ll ori;
ll nez;
bool operator<(const Node &o) const
{
return ori < o.ori;
}
};
int n;
int main()
{
scanf("%d", &n);
vector<Node> v1, v2;
for (int i = 1; i <= n; i++)
{
ll hei;
scanf("%lld", &hei);
v1.push_back({hei, i});
}
for (int i = 1; i <= n; i++)
{
ll hei;
scanf("%lld", &hei);
v2.push_back({hei, i});
}
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
vector<Node> v3;
for (int i = 0; i < n; i++)
{
v3.push_back({v1[i].nez, v2[i].nez});
}
sort(v3.begin(), v3.end());
ll ans = 0;
for (int i = n - 1; i >= 0; i--)
{
ans = (ans + psum(v3[i].nez)) % MOD;
inc(v3[i].nez);
}
printf("%lld", ans);
return 0;
}
此题的离散化不仅要求由数据查ID还要求由ID查数据的双向查询。
inline int lowbit(int x)
{
return x & -x;
}
class Solution
{
public:
int t[10005];
void add(int idx)
{
for (; idx < 10005; idx += lowbit(idx))
t[idx]++;
}
int query(int idx)
{
int ans = 0;
for (; idx; idx -= lowbit(idx))
{
ans += t[idx];
}
return ans;
}
int reversePairs(vector<int> &nums)
{
for(int i = 0;i<10005;i++) t[i] = 0;
vector<long long> N;
for (int i = 0; i < nums.size(); i++)
{
N.push_back(nums[i]);
N.push_back(nums[i] * 2);
}
sort(N.begin(), N.end());
auto it = unique(N.begin(), N.end());
N.erase(it, N.end());
map<int, int> mp;
for (int i = 0; i < N.size(); i++)
{
mp[N[i]] = i + 1;
}
int ans = 0;
for (int i = nums.size() - 1; i >= 0; i--)
{
ans += query(mp[nums[i]] - 1);
add(mp[2ll * nums[i]]);
}
return ans;
}
};