SPOJ 227 Ordering the Soldiers

简介: 点击打开SPOJ227 思路: 树状数组 分析: 1  给定一个n个数的序列假设为b数组,那么b[i]表示的是i之前比第i个数大的个数,比如样例的2 1 3对应的b数组是0 1 0,现在要求a数组,已知a数组的值是1~n 2  我们通...

点击打开SPOJ227

思路: 树状数组

分析:

1  给定一个n个数的序列假设为b数组,那么b[i]表示的是i之前比第i个数大的个数,比如样例的2 1 3对应的b数组是0 1 0,现在要求a数组,已知a数组的值是1~n


2  我们通过b数组可以知道a数组的情况,因为前面的数会影响后面的数,那么我们从后面枚举b数组,这样我们可以知道对于第i个数i-b[i]就是剩下的i个数中的第几大的数,比如第二个样例

    0 1 2 0 1 , 那么i为5的时候i-b[i] = 5-1 = 4,说明第5的数是1~n中的第四大的数也就是4,接下来我们删除掉4,i为4的时候i-b[i] = 4-0 = 4也就是第四个数是剩下的第4大的数也就是5,以此类推.....


3  通过2的思路,我们发现很简单,但是我利用vector的时候TLE了,说明我们需要一个更高效率的算法


4  由于n个数是1~n,那么我们初始化一个树状数组treeNum[i] = i;

    表示的是前面有i个数比它小,那么我们可以知道树状数组是一个单调递增,为什么呢?因为我们初始化每个点的值都还没被取过,那么区间[1,i]的和为i,所以i越大和越大。

    通过第2点的分析我们可以知道,我们能够求出每一个数的排名,也就是前面比它小的个数,那么这个就是树状数组保存的值,所以我们可以通过二分答案来求,我们取了某个数之后就标为true,然后树状数组进行单点更新。

    但是我们会遇到一个问题就是比如第二个样例中我们把4和5取完之后我们会发现[1,3]和[1,4]和[1,5]这三个区间的和为3,但是只有3是符合的,因为4和5被取了,所以我们在二分的时候应该注意判断值是否被取过


5  那么我们来分析一下时间复杂度,我们需要枚举b数组为O(n),每次二分的时间为O(logn),每次更新树状数组的时间为O(logn),总的为O(n*logn*logn)


代码:

/***********************************************
* By: chenguolin                               * 
* Date: 2013-08-19                             *
* Address: http://blog.csdn.net/chenguolinblog *
***********************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN = 200010;

int n;
int num[MAXN];
int treeNum[MAXN];
bool isSelect[MAXN];

int lowbit(int x){
    return x&(-x);
}

int getSum(int x){
    int sum = 0;
    while(x){
         sum += treeNum[x];
         x -= lowbit(x);
    }
    return sum;
}

void add(int x , int val){
    while(x < MAXN){
         treeNum[x] += val;
         x += lowbit(x);
    }
}

void init(){
    memset(isSelect , false , sizeof(isSelect));
    memset(treeNum , 0 , sizeof(treeNum));
    for(int i = 1 ; i <= n ; i++)
        add(i , 1);
}

int search(int x){
    int left = 1;
    int right = n;
    while(left <= right){
         int mid = (left+right)>>1;
         int sum = getSum(mid);
         if(sum == x){
             if(!isSelect[mid]) 
                 return mid;
             right = mid-1; 
         }
         else if(sum < x)
             left = mid+1;
         else
             right = mid-1;
    }
}

void solve(){
    init();
    int output[MAXN];
    for(int i = n ; i >= 1 ; i--){
        int x = i-num[i];
        int ans = search(x);
        output[i] = ans;
        isSelect[ans] = true;
        add(ans , -1);
    }
    printf("%d" , output[1]);
    for(int i = 2 ; i <= n ; i++)
        printf(" %d" , output[i]);
    puts("");
}

int main(){
    int cas;
    scanf("%d" , &cas);
    while(cas--){
         scanf("%d" , &n);
         for(int i = 1 ; i <= n ; i++) 
             scanf("%d" , &num[i]);
         solve();
    }
    return 0;
}




目录
相关文章
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
2409 2
|
7月前
|
存储 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL 数据库课程设计:开启数据宇宙的传奇之旅
本文全面剖析数据库课程设计 MySQL,展现其奇幻魅力与严峻挑战。通过实际案例凸显数据库设计重要性,详述数据安全要点及学习目标。深入阐述备份与恢复方法,并分享优秀实践项目案例。为开发者提供 MySQL 数据库课程设计的全面指南,助力提升数据库设计与管理能力,保障数据安全稳定。
大数据新视界--大数据大厂之MySQL 数据库课程设计:开启数据宇宙的传奇之旅
|
9月前
|
存储 人工智能 安全
实时拦截攻击并响应威胁,聊聊服务器DDoS防御软件
实时拦截攻击并响应威胁,聊聊服务器DDoS防御软件
310 16
|
5月前
|
人工智能 搜索推荐 数据可视化
用 Python 制作简单小游戏教程:手把手教你开发猜数字游戏
本教程详细讲解了用Python实现经典猜数字游戏的完整流程,涵盖从基础规则到高级功能的全方位开发。内容包括游戏逻辑设计、输入验证与错误处理、猜测次数统计、难度选择、彩色输出等核心功能,并提供完整代码示例。同时,介绍了开发环境搭建及调试方法,帮助初学者快速上手。最后还提出了图形界面、网络对战、成就系统等扩展方向,鼓励读者自主创新,打造个性化游戏版本。适合Python入门者实践与进阶学习。
615 1
|
7月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
477 70
|
6月前
|
域名解析 网络协议 数据安全/隐私保护
docker search 超时
docker search超时问题
1515 14
docker search 超时
|
网络协议 Python
Python实现HTTP 传输的断点续传机制
使用Python `requests`库实现HTTP断点续传下载大文件,通过设置`Range`头部从上次中断的位置开始继续下载。示例代码展示了一个名为`resume_download`的函数,它接收URL、文件名和最后字节位置参数,以追加方式打开文件并逐块写入内容。要启用HTTP长连接,可添加`Connection: keep-alive`到请求头。
773 0
|
JavaScript 前端开发 API
一个非常 nb 的 Vue 组件 (含Vue3版本)
一个非常 nb 的 Vue 组件 (含Vue3版本)
|
人工智能 前端开发 Linux
Python编程:利用ImageMagick转换PDF为图片并识别提取图表
Python编程:利用ImageMagick转换PDF为图片并识别提取图表
486 0
|
消息中间件 Shell Linux
RabbitMQ部署指南
主要是如何部署RabbitMQ的具体步骤