这道题在一定程度上体现了线段树的一种用法,解决的问题是:对于总计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. BeanNameAware接口和BeanFactoryAware接口

    迄今为止,所接触到的Bean都是“无知觉”的,就像黑客帝国中机械工厂里面“养殖”的人类,他们虽然能完成一定的功能,但是根本不知道自己在工厂(BeanFactory)中的代号(id),或者自己是在哪个工 ...

  2. rehat 出现GDB debuginfo-install 问题处理

    本人使用rhel 6    GDB 调试代码时,出现以下错误: Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166 ...

  3. 降维PCA技术

    降维技术使得数据变得更易使用,并且它们往往能够去除数据中的噪声,使得机器学习任务往往更加精确. 降维往往作为预处理步骤,在数据应用到其它算法之前清洗数据.有很多技术可以用于数据降维,在这些技术中,独立 ...

  4. R中的name命名系列函数总结

    本文原创,转载请注明出处,本人Q1273314690 R中关于给行列赋名称的函数有 dimnames,names,rowname,colname,row.names 这五个函数,初学的时候往往分不清楚 ...

  5. mysql搜索引擎 小结

    mysql搜索引擎 小结 mysql5.5以后,mysql默认使用InnoDB存储引擎. 若要修改默认引擎,可以修改配置文件中的default-storage-engine.可以通过show vari ...

  6. ubuntu安装ssh

    为了解决远程连接ubuntu服务器控制端,方便操作.ubuntu不同的版本安装方式一致!首先在ubuntu服务器下安装SSH服务linux安装命令:sudo apt-get install opens ...

  7. CodeForces 353B Two Heaps

    B. Two Heaps   Valera has 2·n cubes, each cube contains an integer from 10 to 99. He arbitrarily cho ...

  8. oracle 使用ID关键字作列名导致索引失效

    oracle表空间变更导致主键索引失效,重建索引即可

  9. UI第五节——手势

    #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL ...

  10. Timestamp 使用

    Timestamp是一个长整形的类型 1.使用方法一 Timestamp nowdate1 = new Timestamp(System.currentTimeMillis()); System.ou ...