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

    <!--开发后删除--> <meta http-equiv="Pragma" name="no-store" /><!--必须联网 ...

  2. 基础知识系列☞MSSQL→约束

    遇到一个数据库设计很渣的系统··· 本来一个约束就能解决的问题·以前建库的时候也不设计好···

  3. HDOJ 4751 Divide Groups

    染色判断二分图+补图 比赛的时候题意居然是反的,看了半天样例都看不懂 .... Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memo ...

  4. 第12天 android studio

    1. http://jingyan.baidu.com/article/215817f7888dc21eda14230d.html Gradle DSL method not found:‘andro ...

  5. SQL按指定文字顺序进行排序(中文或数字等)

    在有些情况下我们需要按指定顺序输出数据,比如选择了ID in(3,1,2,5,4)我们希望按这个3,1,2,5,4的顺序输出,这样只使用order by ID是无法实现的, 但是我们可以使用order ...

  6. EF初接触01

    自动属性:{get;set} 隐式类型 var, dynamic var:  隐式的类型推断出来,在编译阶段把Var换成对应的实际的类型 所以只应用在编译之间, 在运行阶段是和实际类型意义的 dyna ...

  7. java中二进制和流的相互转换

    流转二进制 public static byte[] toByteArray(InputStream in) throws IOException { ByteArrayOutputStream ou ...

  8. 剑指Offer 两个链表的第一个公共结点

    题目描述 输入两个链表,找出它们的第一个公共结点.   思路: 题目说的很笼统,应该是有2个链表,找出公共点,第一个公共点后面的链表是共同所有的.可以用map做,直接检测map里有没有出现这个节点. ...

  9. cvLoadImage

    编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 函数原型:IplImage* cvLoadImage( const char* filename, int flags= ...

  10. ajax 载入html后不能执行其中的js解决方法

    事件背景 有一个公用页面需要在多个页面调用,其中涉及到部分js已经写在了公用页面中,通过ajax加载该页面后无法执行其中的js. 解决思路 1. 采用附加一个iframe的方法去执行js,为我等代码洁 ...