这道题在一定程度上体现了线段树的一种用法,解决的问题是:对于总计n个元素的第i个元素,已知其在[1,i]上部分序列的排名,求第i个元素在所有n个元素中的排名。

当然这道题数据比较水,所以用O(n^2)的直接解法也可以解出,在这里,我也给出自己的O(n^2)解法。


  题目大意:

    n头乱序的牛排列在一行,每头牛都有一个牌号(1-n),现在知道所有牛此前有多少头牛的牌号比该牛的牌号要小,求每头牛的牌号。

  直接解法(插入式):

    从前向后遍历每一个数据,每次都进行一次插入。

    具体来说:例如对于(1,0,1)这样的序列,我们先设brand[1] = 1。

      由第一个数据(1)有brand[2] = 2    ————有排名为:(1,2)

      由第二个数据(0)有brand[3] = 1,此时遍历此前所有元素,查询到>=brand[3]则加一个排名,得到brand[1] = 2,brand[2] = 3;  ——排名(2,3,1)

      由第三个数据(1)有brand[4] = 2,此时遍历此前元素,参照上面的方法,得到brand[1] = 3,brand[2] = 4;  ——(3,4,1,2)

    那么最后能够得到排名(3,4,1,2);

  Code如下:

 //普通的O(n^2)算法-直接的想法
//n头牛,已知第i头牛在1-i部分序列的排名,求所有牛的牌号(排名)
//Memory: 236K Time:375Ms
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 8005
int n; //cow头量
int small[MAX]; //比第i头cow靠前但牌号较小的cow头量
int brand[MAX]; //牌号
int main()
{
scanf("%d", &n);
brand[] = ;
for (int i = ; i <= n; i++)
{
scanf("%d", &small[i]);
brand[i] = small[i] + ;
if (small[i] + != i) //不是排在最后
{
for (int j = ; j < i; j++)
{
if (brand[j] >= brand[i]) //>=该序号则+1
brand[j]++;
}
}
}
for (int i = ; i <= n; i++)
printf("%d\n", brand[i]);
return ;
}

插入式-解法


  线段树解法:

    大体想法就是:用线段树存储一个从1-n的顺序排名,将数据从后向前遍历,每次遍历到某一个位置时,假设原数据为s[],那么对于s[i],其在1-i的排名就是s[i]+1,那么在线段树中将[s[i]+1,s[i]+1]区间的sum置为0(减去1)。也就是删去s[i]+1这个排名,这样排名的整体规模就缩小了一个单位,即原为n个元素排名,现在是n-1个元素排名(第s[i]+1排名被删去),并保留原排名数值不变。

    这样不断遍历,不断缩减排名的规模就可以依次反向得到该乱序的牛的牌号,然后顺序输出牌号即可

  Code如下:

  

 //线段树
//n头牛,已知第i头牛在1-i部分序列的排名,求所有牛的牌号(排名)
//Memory: 432K Time:47Ms
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 8005
int n; //cow头量
int small[MAX]; //比第i头cow靠前但牌号较小的cow头量
int brand[MAX]; //牌号
//Brand interval数组
struct Brands{
int l, r; //牌号区间
int sum; //头数
}tree[*MAX];
/*从x开始搭建interval tree*/
void build(int x,int l,int r)
{
tree[x].l = l;
tree[x].r = r;
if (l == r){
tree[x].sum = ;
return;
}
int mid = (l + r) / ;
build( * x, l, mid); //left son
build( * x + , mid + , r); //right son
tree[x].sum = tree[ * x].sum + tree[ * x + ].sum;
}
int query(int x, int v)
{
tree[x].sum--;
// Hit!
if (tree[x].l == tree[x].r)
return tree[x].l;
if (v <= tree[ * x].sum) //<=左结点未删减序列数量
query( * x, v);
else query( * x + , v - tree[ * x].sum);
}
int main()
{
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%d", &small[i]);
small[] = ;
build(, , n);
for (int i = n; i >= ; i--)
brand[i] = query(, small[i] + ); //牌号
for (int i = ; i <= n; i++)
printf("%d\n", brand[i]);
return ;
}

线段树-解法


ACM/ICPC 之 数据结构-线段树思想(POJ2182,含O(n^2)插入式解法)的更多相关文章

  1. ACM/ICPC 之 数据结构-线段树+区间离散化(POJ2528)

    这道题用线段树做更方便更新和查询,但是其数据范围很大,因此要将离散化和线段树结合起来,算是一道比较经典的线段树+离散化的例题. 线段树的离散化有很多方法,在这里,我先用一次结点离散化,间接将源左右端点 ...

  2. 算法手记 之 数据结构(线段树详解)(POJ 3468)

    依然延续第一篇读书笔记,这一篇是基于<ACM/ICPC 算法训练教程>上关于线段树的讲解的总结和修改(这本书在线段树这里Error非常多),但是总体来说这本书关于具体算法的讲解和案例都是不 ...

  3. Sum of Squares of the Occurrence Counts解题报告(后缀自动机+LinkCutTree+线段树思想)

    题目描述 给定字符串\(S(|S|\le10^5)\),对其每个前缀求出如下的统计量: 对该字符串中的所有子串,统计其出现的次数,求其平方和. Sample Input: aaa Sample Out ...

  4. ACM: Billboard 解题报告-线段树

     Billboard Time Limit:8000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descript ...

  5. UPC 2224 Boring Counting ★(山东省第四届ACM程序设计竞赛 tag:线段树)

    [题意]给定一个长度为N的数列,M个询问区间[L,R]内大于等于A小于等于B的数的个数. [题目链接]http://acm.upc.edu.cn/problem.php?id=2224 省赛的时候脑抽 ...

  6. CF 787D Legacy(线段树思想构图+最短路)

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  7. ACM: Hotel 解题报告 - 线段树-区间合并

    Hotel Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description The ...

  8. sdut 2159 Ivan comes again!(2010年山东省第一届ACM大学生程序设计竞赛) 线段树+离散

    先看看上一个题: 题目大意是: 矩阵中有N个被标记的元素,然后针对每一个被标记的元素e(x,y),你要在所有被标记的元素中找到一个元素E(X,Y),使得X>x并且Y>y,如果存在多个满足条 ...

  9. ACM-ICPC 2017 Asia Xi'an A XOR (线性基+线段树思想)

    题目链接 题意;给个数组,每次询问一个区间你可以挑任意个数的数字异或和 然后在或上k的最大值 题解:线性基不知道的先看这个,一个线性基可以log的求最大值把对应去区间的线性基求出来然后用线段树维护线性 ...

随机推荐

  1. 使用自己的ClassLoader实现热替换

    首先实现一个自己的ClassLoader,该ClassLoader重写findClass方法. 从classpath中加载类资源. 注意,不要重写loadClass方法.  因为在使用自定义的MyCl ...

  2. asp.net mvc中在使用async的时候HttpContext为null的问题

    摘要 HttpContext上下文并不是无处不在的.详情可以看下Fish Li的文章,解释的比较清楚. HttpContext.Current并非无处不在 问题复现 public async Task ...

  3. Vagrant error: Your VM has become inaccessible.

    博客转自:http://doodlebobbers.com/vagrant-error-your-vm-has-become-inaccessible/ If you’ve deleted a vir ...

  4. 原生JavaScript技巧大收集(11~20)-(终于又被我找到这篇文章了)

    11.原生JavaScript加入收藏夹 function AddFavorite(sURL, sTitle) { try { window.external.addFavorite(sURL, sT ...

  5. Mastering Web Application Development with AngularJS 读书笔记-前记

    学习AngularJS的笔记,这个是英文版的,有些地方翻译的很随意,做的笔记不是很详细,用来自勉.觉得写下来要比看能理解的更深入点.有理解不对的地方还请前辈们纠正! 一.关于<Mastering ...

  6. sql中的常见的全局变量

    select APP_NAME ( ) as w --当前会话的应用程序 select @@IDENTITY --返回最后插入的标识值 select USER_NAME() --返回用户数据库用户名 ...

  7. ajax之get、post

    异步获取数据: <script type="text/javascript"> /** * [showstatus 获取数据] * @return {[type]} [ ...

  8. FineUI第十六天---表格的排序和分页

    表格的排序和分页 1.表格的排序需要: AllowSorting:是否允许排序. SortColumn:当前排序的列ID,当然也可以不设置此属性,而是在后台初始化代码中直接指定默认排序字段. Sort ...

  9. Android--UI之AutoCompleteTextView

    前言 之前讲过EditText,有兴趣的朋友可以看一下.这篇博客主要说明的是自动完成文本框,它实际上也是一个文本编辑框,可以理解为对EditText功能的扩展,它对输入的内容可以进行提示并且自动完成. ...

  10. android socket编程用Bufferreader读取的一个失败教训

    由于我的手机需要用笔记本开的wifi,躺在床上玩手机时需要关电脑或者是要让电脑放歌的时候总是不想下床,于是我想能不能用一个APP,然后通过局域网实现在手机上对电脑进行操控呢?说干就干. 我在电脑上用的 ...