首页 > 其他分享 >题解 B3694 数列离散化

题解 B3694 数列离散化

时间:2024-07-22 15:30:49浏览次数:17  
标签:lower 数列 int 题解 bound 离散 B3694 unique

简而言之,离散化就是把一个数列转化为由小到大的排名来缩小范围。

离散化需要这个题不用数字本身

举个例子:

-2002 448799 1 49932 35793

离散化后就是:

1 5 2 4 3

\(-2002\) 最小,所以它对应 \(1\)

\(448799\) 最大,所以它对应 \(5\)

实现

考虑如何实现。

首先由于离散化前后数的顺序不能发生变化,我们需要复制一份:

for (int i = 1; i <= n; ++i) c[i] = a[i];

然后需要排序来确定顺序:

sort (a + 1, a + n + 1);

最后在 \(C\) 数组中找每个 \(a_i\) 就能确定第 \(i\) 个数的离散化结果了。

for (int i = 1; i <= n; ++i) {
    rank[i] = lower_bound(c + 1, c + n + 1) - c;
}

注意这里为什么不减 (c + 1):题目说 :

定义 \(\mathrm{rank(i)}\) 表示数列 \(a\) 中比 \(a_i\) 小的不同数字个数再加一

所以减去的应少 \(1\)​。

而且由于

lower_bound( begin,end,num):从数组的begin位置到end - 1位置二分查找第一个大于等于num的数字,找到返回该数字的地址,不存在则返回end

则如果某个数不止 \(1\) 个,则 lower_bound 返回的是最后一个的地址,然而我们想要的是第一个。

于是我们就需要去重。

unique 即可。

int cnt = unique(c + 1, c + n + 1) - (c + 1);

于是在 lower_bound 时就需要lower_bound(c + 1, c + cnt + 1)而不是 lower_bound(c + 1, c + n + 1)

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

int n;
int a[N];
int c[N];

void solve() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i]; 
        c[i] = a[i];
    }
    sort (c + 1, c + n + 1);
    int cnt = unique(c + 1, c + n + 1) - (c + 1);
    for (int i = 1; i <= n; ++i) {
        a[i] = lower_bound(c + 1, c + cnt + 1, a[i]) - c;
    }
    for (int i = 1; i <= n; ++i) cout << a[i] << " "; //不是 c[i]!!!
    cout << '\n';
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);

    int T; cin >> T; while (T --) solve();
    return 0;
}

标签:lower,数列,int,题解,bound,离散,B3694,unique
From: https://www.cnblogs.com/lstylus/p/18316084

相关文章

  • 【Web】ImaginaryCTF 2024 部分题解
    目录journalcrystalsP2CreadmeTheAmazingRacejournal简单的assert命令拼接payload:?file=test','..')===true||system("echo`tac/flag-cARdaInFg6dD10uWQQgm.txt`")||strpos('testcrystalsdocker-compose.yml里让服务报错读到泄露的hos......
  • 题解:牛客周赛 Round 52 A
    A两数之和时间限制:C/C++1秒,其他语言2秒空间限制:C/C++262144K,其他语言524288KSpecialJudge,64bitIOFormat:%lld题目描述对于给定的正整数\(z\),你需要寻找两个不同的正整数\(x\)和\(y\),使得\(x+y=z\)成立。如果不存在这样的\(x\)和\(y\),你只需要输出NO。......
  • ABC363 DEF 题解
    ABC363DEF题解前情提要:赛时过了ABCE。D-PalindromicNumber题目链接其实赛时已经看出了一些性质,但没想完做法,赛后看题解才发现这么简单/fn首先,为了方便,我们不把\(0\)视作回文数(因此需要特判一下\(n=1\)的情况)。下面要证明:\(d\)位回文数有\(10^{\left\lfloor\f......
  • 题解 P1115 最大子段和
    link容易想到朴素做法:for(intl=1;i<=n;++i){for(intr=1;j<=n;++j){intv=s[r]-s[l-1];ans=max(ans,v);}}但是显然\(\mathrm{\color{#052242}TLE}\)再回头看代码:想要v最大,只需要\(\large{S_{l-1}}\)最小即可......
  • 题解:P7482 不条理狂诗曲
    题解:P7482不条理狂诗曲本题解借鉴blossom_j大佬思路,但这位大佬的题解似乎没放正确代码。题意对于每一个\(a\)的子区间\(a_{l\dotsr}\),求选择若干个不连续的数的和的最大值,对答案取模\(10^{9}+7\)。思路主要算法:分治。计算跨过中点\(mid\)的区间的\(f\)之和。首......
  • P3041 [USACO12JAN] Video Game G 题解 AC自动机
    本题是一道AC自动机上的dp。首先不难想到状态定义f(i,j)表示仅考虑前i 个位置,第i 个字符是j 的分数,但无法转移,所以考虑将j这一维转化为表示AC自动机上的点。再定义val(i)表示以i 结尾的所有技能种数,则转移方程为f(i,j)=max(f(i,j),f(i-1,father(j)+val(j......
  • Loj P10064 黑暗城堡 题解 最短路径树记数
    这道题是一道最短路径树问题。首先,什么是最短路径树呢?定义一个图的最短路径树表示一个图上的生成树,且根节点到图上任一点的距离等于原图上两者之间的距离。而不难发现,题目其实是在求图上最短路径树记数。首先,建出最短路径树。枚举每条边,判断边两个端点到根的距离之差是否为......
  • 【题解】P4648 [IOI2007] pairs 动物对数
    Problem给定模板\(B(1\leB\le3)\),代表\(B\)维空间。其中有\(n\)个点,给出坐标与坐标上限\(M\),求\(n\)个点中曼哈顿距离\(\leD\)的对数。Solve\(B=1\)考虑将问题化简成:求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^{i-1}[dis(i,j)\leqD]\)。其中\(dis(i,j)\)......
  • 圆方树学习笔记 & 最短路 题解
    前言圆方树学习笔记,从一道例题讲起。题目链接:Hydro&bzoj。题意简述仙人掌上求两点距离。题目分析为了把仙人掌的性质发挥出来,考虑将其变成一棵树。圆方树就是这样转换的工具。先讲讲圆方树的概念:原图上的点为圆点,每个点双对应一个方点,树边都是方点连向点双内的圆点。具......
  • 跑步爱天天 题解
    题意简述一棵以\(1\)为根的树,儿子间有先后顺序。初始每个结点上有一个警卫,警卫按照深度优先遍历其子树,儿子间的先后顺序体现在这里,回到起始点后开始新一轮的遍历。yzh想要从\(S\)走到\(1\),请问她会在路上遇到多少警卫(\(S\)点的也算)。题目分析法\(1\)先来讲一讲我考场......