首页 技术 正文
技术 2022年11月9日
0 收藏 536 点赞 2,435 浏览 3604 个字

题目大意

n个数排成一排(不知道大小,只是占了一个位置),从a[1]到a[n]进行遍历,对于每个a[i],给出从a[1]到a[i-1]中小于a[i]数的个数。要求出 a[1]到a[n]中这n个数的相对顺序。

题目分析

对于每个数 a[i], 给出了从 a[1] — a[i-1]中小于a[i]的个数 less[i]. 
    从n到1逆序查看, less[n] 表示前n-1个数中小于a[n]的个数,则可以确定a[n]的位置为 less[n] + 1 
类似的对于 i,为了确定a[i]在所有n个数中的序号,将这个任务分为两部分: 
(1)在 a[1] — a[i-1]中有多少个数小于a[i], 题目给出了为 less[i] 
(2)在a[i+1]—a[n]中有多少个数小于 a[i], 设为t

则 a[i] 在所有n个数中的序号(按照从小到大排序)为 k = less[i] + t + 1

但是,t并不好直接求出,则观察k的性质。对于a[i]在所有n个数中的位置k,1—k-1中包括 less[i]个在 a[1] — a[i-1]中的元素,同时包括t个在a[i+1]—a[n]中的元素,在a[i+1]—a[n]中的元素已经确定了他们在整个n个数中的位置(我们是从后往前进行计算的),则 1—-k-1中就可以确定那t个元素的位置。

为了确定k的位置,则设置一个数组b[1]–b[n],初始全部为0,从n到1统计,若a[i]的位置确定下来为p,则 b[p] = 1.则对于任意的k,b[1]—b[k]中1的个数表示 1—-k中被占用的位置,0 的位置表示未被占用的位置。

对于 a[i],找到某个k,使得其b[1]–b[k-1]中0的个数正好为 less[i]个,则k的位置就是 a[i]在整个n个数中的按照大小排序的位置

实现(c++)

1. 线段树

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>#define MAX_COW_NUM 80010
#define MAX_NODE_NUM 4*MAX_COW_NUMint gLess[MAX_COW_NUM];
int gPos[MAX_COW_NUM];
struct Node{
int beg;
int end;
int sum_zero;
int Mid(){
return (beg + end) >> 1;
}
};
Node gNodes[MAX_NODE_NUM];
void BuildTree(int beg, int end, int index){
gNodes[index].beg = beg;
gNodes[index].end = end;
if (beg == end){
gNodes[index].sum_zero = 1;
return;
}
int left = 2 * index + 1;
int right = 2 * index + 2;
int mid = (beg + end) >> 1;
BuildTree(beg, mid, left);
BuildTree(mid + 1, end, right);
gNodes[index].sum_zero = gNodes[left].sum_zero + gNodes[right].sum_zero;
}
//对于每个数 a[i], 给出了从 a[1] -- a[i-1]中小于a[i]的个数 less[i].
//从n到1逆序查看, less[n] 表示前n-1个数中小于a[n]的个数,则可以确定a[n]的位置为 less[n] + 1
//类似的对于 i,为了确定a[i]在所有n个数中的序号,将这个任务分为两部分:
//(1)在 a[1] -- a[i-1]中有多少个数小于a[i], 题目给出了为 less[i]
//(2)在a[i+1]---a[n]中有多少个数小于 a[i], 设为t//则 a[i] 在所有n个数中的序号(按照从小到大排序)为 k = less[i] + t + 1//t 并不好直接求出,则观察k的性质。对于a[i]在所有n个数中的位置k,1---k-1中包括 less[i]个在 a[1] -- a[i-1]中的元素,
//同时包括 t个在a[i+1]---a[n]中的元素,在a[i+1]---a[n]中的元素已经确定了他们在整个n个数中的位置(我们是从后往前进行计算的),
//则 1----k-1中就可以确定那t个元素的位置。//为了确定k的位置,则设置一个数组 b[1]--b[n],初始全部为0,从n到1统计,若a[i]的位置确定下来为p,则 b[p] = 1.
//则对于任意的k,b[1]---b[k]中1的个数表示 1----k中被占用的位置,0 的位置表示未被占用的位置。//对于 a[i],找到某个k,使得其b[1]--b[k-1]中0的个数正好为 less[i]个,则k的位置就是 a[i]在整个n个数中的按照大小排序的位置//利用线段树,找到 b[1]---b[pos]中 0的个数为k个的pos的位置
void FindKth(int k, int index, int& pos){
if (gNodes[index].sum_zero < k){
return;
}
if (gNodes[index].beg == gNodes[index].end){
gNodes[index].sum_zero = 0;
pos = gNodes[index].beg;
return;
}
int left = 2 * index + 1, right = 2 * index + 2;
gNodes[index].sum_zero--;
if (gNodes[left].sum_zero >= k){
FindKth(k, left, pos);
}
else{
FindKth(k - gNodes[left].sum_zero, right, pos);
}
}int main(){
int n;
scanf("%d", &n);
BuildTree(0, n - 1, 0);
for (int i = 2; i <= n; i++){
scanf("%d", &gLess[i]);
}
int pos = 0;
gLess[1] = 0;
for (int i = n; i >= 1; i--){
FindKth(gLess[i] + 1, 0, pos);
gPos[i] = pos + 1;
}
for (int i = 1; i <= n; i++){
printf("%d\n", gPos[i]);
}
return 0;
}

 2. 树状数组

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define MAX_COW_NUM 80010
int gLowBit[MAX_COW_NUM];
int gC[MAX_COW_NUM];
int gLess[MAX_COW_NUM];
int gPos[MAX_COW_NUM];
bool gUsed[MAX_COW_NUM];
void InitLowBit(int n){
for (int i = 1; i <= n; i++){
gLowBit[i] = i&(-i);
}
}
void InitSequence(int n){
for (int i = 1; i <= n; i++){
gC[i] = gLowBit[i];
}
}//树状数组的更新
void Update(int p, int n, int add){
while (p <= n){
gC[p] += add;
p += gLowBit[p];
}
}//树状数组的查询
int Query(int p){
int result = 0;
while (p > 0){
result += gC[p];
p -= gLowBit[p];
}
return result;
}//二分法,查找满足要求的 位置
int Search(int k, int n){
int beg = 1, end = n + 1;
while (beg < end){
int mid = (beg + end) >> 1;
int sum_zero = Query(mid);
if (sum_zero == k){
while (mid + 1 < end){//用于判断该位置是否被占用
if (gUsed[mid + 1])
mid++;
else
break;
}
return mid + 1;
}
else if (sum_zero < k){
beg = mid + 1;
}
else{
end = mid;
}
}
return 1;
}int main(){
int n;
scanf("%d", &n);
gLess[1] = 0;
InitLowBit(n);
InitSequence(n);
memset(gUsed, false, sizeof(gUsed));for (int i = 2; i <= n; i++){
scanf("%d", &gLess[i]);
}
for (int i = n; i >= 1; i--){
int pos = Search(gLess[i], n);
gPos[i] = pos;
gUsed[pos] = true;
Update(pos, n, -1);
}
for (int i = 1; i <= n; i++){
printf("%d\n", gPos[i]);
}
return 0;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,487
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,127
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289