链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小w向大家介绍了离散化处理的具体操作过程。离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。
假设原数组为a[]数组,将其离散化后得到b[]数组,我们要求满足b数组满足以下几点:
1、离散化数组应保留原数组的大小关系,即当a[i]>a[j]时,必有b[i]>b[j],a[i]=a[j]时,必有b[i]=b[j],a[i]<a[j]时,必有b[i]<b[j]。
2、b数组由正整数构成。
3、在满足以上两点的情况下,b数组的每个元素都要求尽可能的小。
比如说对{100,200,500,200,300}进行离散化后将会变成{1,2,4,2,3}。
为了考验大家是不是真的学会了离散处理,小w准备来考考大家。
小w现在有一个长度为n的a[]数组,下标从1到n,并且满足a[i]∈[1,1000000000]。
每次小w会选择一段L到R的子数组,问,如果把这段子数组进行离散化处理后,将会有多少个元素跟原来不同?
输入描述:
对于每组案例,首先输入一个正整数n。(1<=n<=300000) 接下来一行n个正整数a[i](1<=a[i]<=1000000000)表示a数组每个元素。 接下来一个正整数m,表示小w有m个问题。(1<=m<=300000) 接下来m行,每行两个正整数L,R(1<=L<=R<=n)表示小w选中的子数组由a[L],a[L+1],a[L+2]....a[R-1],a[R]组成,并且问你将其离散化后将会有多少个元素发生改变。
输出描述:
对于每个查询,输出一行一个整数,表示查询的答案。
示例1
输入
9 4 3 1 2 5 3 3 1 4 8 1 3 2 4 2 5 1 5 3 7 4 7 4 8 5 9
输出
2 0 1 0 1 4 1 4
说明
第一个查询表示的子数组为{4,3,1},将其离散化后得到{3,2,1},有两个元素发生变化。 第二个查询表示的子数组为{3,1,2},将其离散化后得到{3,1,2},没有任何元素元素发生变化。 第三个查询表示的子数组为{3,1,2,5},将其离散化后得到{3,1,2,4},有一个元素元素发生变化。 第四个查询表示的子数组为{4,3,1,2,5},将其离散化后得到{4,3,1,2,5},没有任何元素元素发生变化。 第五个查询表示的子数组为{1,2,5,3,3},将其离散化后得到{1,2,4,3,3},有一个元素元素发生变化。 第六个查询表示的子数组为{2,5,3,3},将其离散化后得到{1,3,2,2},有四个元素元素发生变化。 第七个查询表示的子数组为{2,5,3,3,1},将其离散化后得到{2,4,3,3,1},有一个元素元素发生变化。 第八个查询表示的子数组为{5,3,3,1,4},将其离散化后得到{4,2,2,1,3},有四个元素元素发生变化。
备注:
每个查询都是独立的,并不会改变a数组的组成。
解析:
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
typedef long long LL;
#define int LL
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 1 << 21;
const int N = 3e5 + 10, M = 2 * N;
int n, m;
int a[N];
struct Node {
int l, r, id;
int ansl, ansr, mex;
}Q[N];
int tr[N << 2], C[N];
#define ls u<<1
#define rs u<<1|1
bool cmp1(const Node& A, const Node& B) {
return A.r < B.r;
}
bool cmp2(const Node& A, const Node& B) {
return A.l < B.l;
}
bool cmp3(const Node& A, const Node& B) {
return A.id < B.id;
}
void updata(int u,int l,int r,int pos,int d) {
if (l == r) {
tr[u] = pos;
return;
}
int mid = l + r >> 1;
if (d <= mid) {
updata(ls, l, mid, pos, d);
}
else {
updata(rs, mid + 1, r, pos, d);
}
tr[u] = min(tr[ls], tr[rs]);
}
int query(int u, int l, int r, int d) {
if (l == r) {
return l;
}
int mid = l + r >> 1;
if (tr[ls] < d) {
return query(ls, l, mid, d);
}
else {
return query(rs, mid + 1, r, d);
}
}
void add(int x, int d) {
for (; x <= n; x += x & -x) {
C[x] += d;
}
}
int ask(int x) {
int ret = 0;
for (; x; x -= x & -x) {
ret += C[x];
}
return ret;
}
signed main() {
memset(tr, -1, sizeof tr);
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
cin >> m;
for (int i = 1; i <= m; i++) {
scanf("%lld%lld", &Q[i].l, &Q[i].r);
Q[i].id = i;
}
sort(Q + 1, Q + 1 + m, cmp1);
for (int i = 1, pos = 1; i <= n; i++) {
if (a[i] <= n) {
updata(1, 1, n, i, a[i]);
add(a[i], 1);
}
for (; Q[pos].r == i && pos <= m; pos++) {
Q[pos].mex = query(1, 1, n , Q[pos].l);
Q[pos].ansr = ask(Q[pos].mex);
//cout << "_______________________" << Q[pos].mex <<" "<<Q[pos].ansr<<" "<<Q[pos].id<< endl;
}
}
sort(Q + 1, Q + 1 + m, cmp2);
memset(C, 0, sizeof C);
for (int i = 0, pos = 1; i <= n; i++) {
if (i && a[i] <= n) {
add(a[i], 1);
}
for (; Q[pos].l - 1 == i && pos <= m; pos++) {
Q[pos].ansl = ask(Q[pos].mex);
//cout << ":::::::::::::::: " << Q[pos].ansl << " " << Q[pos].id << endl;
}
}
sort(Q + 1, Q + 1 + m, cmp3);
for (int i = 1; i <= m; i++) {
//cout << "++++++++++++++ " << Q[i].ansr << " " << Q[i].ansl <<" "<<Q[i].mex<< endl;
printf("%lld\n", Q[i].r - Q[i].l + 1 - (Q[i].ansr - Q[i].ansl));
}
return 0;
}
/*
9
4 3 1 2 5 3 3 1 4
8
1 3
2 4
2 5
1 5
3 7
4 7
4 8
5 9
*/