POJ 2828 线段树活用
题目大意:依次描述了一个N个人的队伍,每个人所站的序号以及他的价值,依次描述每个人的过程中,存在序号相同的人,表示该人插入到了前一个序号相同的人的前面。最后输出整个队伍的值排列情况。
这个题目确实难以想到居然可以用线段树做,之前还脑残去敲什么链表,结果发现链表这玩意儿真不是一般的垃圾,好多地方根本就无法对时间进行优化。
当然了,就算告诉了你用线段树做,可能还是会很头疼,这里涉及插队操作。。而且线段树具体是存放什么东西的呢
线段树就是为了模拟当前队伍的空位数,比如一个4人队伍,Root肯定是值为4 然后左右孩子都为 2 2 ,最底下4个孩子均为1,表示该位置还可以插入几个人
插队操作是比较蛋疼的,为了避免插队,大牛们给的神思路是从后往前遍历,原理很简单,如果是插队,那从后往前,最后一个插队的,必定是站在他插得位置,扫到前面,被插队的人,因为插队的人已经占据了线段树的一个孩子,所以被插队的人只能乖乖自己选择后面的孩子。由此,问题迎刃而解。
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 200005
#define Lson (x<<1),l,mid
#define Rson (x<<1|1),mid+1,r
using namespace std;
int d[maxn*];
int pos[maxn],v[maxn];
int ans[maxn];
void getup(int x)
{
d[x]=d[x<<]+d[x<<|];
}
void build (int x,int l,int r)//建树如同上面的分析,使得整棵树用来存队伍里的空位数
{
if (l==r)
{
d[x]=;
return;
}
int mid=(l+r)/;
build(Lson);
build(Rson);
getup(x);
}
void query(int loc,int rec,int x,int l,int r)
{
if (l==r)
{
d[x]--; //找到了对应的空位,则空位数--;
ans[l]=v[rec];//l保存了当前是队伍第几个
return;
}
int mid=(l+r)/;
if (loc<=d[x<<]) query(loc,rec,Lson);
else
query(loc-d[x<<],rec,Rson);//这里的比较需要注意,我之前一度弄混成比较loc和l,loc虽然代表了需要插入到队伍的位置,但也可以理解为空位数,即,假如loc=2,则可以理解为必须要有两个或者两个以上空位,否则转向右孩子,但loc值要减掉左孩子的空位值,意思就是左孩子已经提供了这么多空位。
getup(x); //及时将空位情况更新
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
build(,,n);
int i,j;
for (i=; i<=n; i++)
{
scanf("%d %d",&pos[i],&v[i]);
}
for (j=n; j>=; j--)
{
query(pos[j]+,j,,,n); //由于题目给的序号是从0开始,建树什么的,我都喜欢从1开始,故这里pos+1.
}
for (i=; i<n; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return ;
}
POJ 2828 线段树活用的更多相关文章
- poj 2828 线段树
http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 而且后来的也能够确定----假设从前往后 ...
- poj 2828(线段树 逆向思考) 插队是不好的行为
http://poj.org/problem?id=2828 插队问题,n个人,下面n行每行a,b表示这个人插在第a个人的后面和这个人的编号为b,最后输出队伍的情况 涉及到节点的问题可以用到线段树,这 ...
- POJ 2828 线段树(想法)
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 15422 Accepted: 7684 Desc ...
- poj 2828(线段树单点更新)
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 18561 Accepted: 9209 Desc ...
- POJ 2828 (线段树 单点更新) Buy Tickets
倒着插,倒着插,这道题是倒着插! 想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0. 从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的 ...
- POJ 2828 线段树 逆序插入
思路: 1.线段树 逆着插入就OK了 2.块状链表 (可是我并不会写) //By SiriusRen #include <cstdio> #include <cstring> ...
- POJ 2828 线段树单点更新 离线搞
Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...
- poj 2886 线段树+反素数
Who Gets the Most Candies? Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12744 Acc ...
- poj 3468(线段树)
http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...
随机推荐
- 014、Java中byte自动转型的操作
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 019.CI4框架CodeIgniter辅助函数类之:Array数组查询
01. 数组辅助函数,可以方便的查看数组内部的成员,用法如下图所示: <?php namespace App\Controllers; class Hello extends BaseContr ...
- RDD 可视化 —— RDDOperationScope.withScope
最近在看各种博客,学习 spark 源代码. 网上对源代码的分析基本都是基于 0.7, 0.8, 1.0 的代码,而现在的发行版已经是 1.5 了.所以有些代码不大对的上.比如函数 RDD.map() ...
- 比较 CEILING 和 FLOOR
CEILING 函数返回大于或等于所给数字表达式的最小整数. FLOOR 函数返回小于或等于所给数字表达式的最大整数. 例如,对于数字表达式 12.9273,CEILING 将返回 13,FLOOR ...
- Notepad2&Notepad++
写在前面 几个礼拜前电脑自带的记事本抽风,打开文本后台有进程但就是不显示界面,网上搜的教程无非是重装.杀毒.换包;这些操作要不就是太繁琐要不就是没效果,于是乎我物色了两款十分强大且轻量的开源记事本No ...
- 官网英文版学习——RabbitMQ学习笔记(三)Hello World!
参考http://www.rabbitmq.com/tutorials/tutorial-one-java.html,我们直接上代码,由于我们的RabbitMQ服务是安装在虚拟机上的,具体参考上一节. ...
- 微服务框架中springboot启动的一个问题
微服务中,采用的是springboot构建单个项目,其中一个项目user启动过程中总是启动补起来,相关的地方都没有错,始终启动不起来,而且要命的是控制台不打印日志,日志级别是debug级别的,但是打印 ...
- nodeks —— fs模块 —— 从流中 读取和写入数据
Fs流读取和写入数据 使用文件流来读取大文件不会卡顿 1, 从流中读取数据 var fs = require("fs"); var data = ''; var count = 0 ...
- jquery快速常用技能
jQuery入口函数与js入口函数 (window.onload = function(){})的对比: 1.JavaScript的入口函数要等到页面中所有资源(包括图片.文件)加载完成才开始执行. ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 动态内存
栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存. 可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址.这种运 ...