POJ 2828 线段树
2015-09-21 21:02
316 查看
线段树单点更新
这道题写线段树是很简单的操作,但是最重要的是思路,因为很难想到。因为是插队插入的,所以换个方向思考,最后插入的一定是该位置,然后忽略该位置,后面同理。
主要思路:
现在看样例这组数据,因为上面已经说过了,所以我们先要把所有的输入存储起来,于是从最后一条输入来看,3 69(位置先自加1)说明了前面是有2个空位的,于是这时候就要插入到第3个位置中(原因在于此时序列中没有其他数字,所以在第三个位置),然后进来2 33 现在这条数据在第二个空位那里,然后最关键的一条数据 2 51 ,这条数据进来后发现它应该在第二个空位里面,这时候我们看这条序列_ 33 69 _,这时候第二个空位是69之后的位置,所以此时的序列为_ 33 69 51,最后一条信息1 77进来后此时应该放在第一个空位上,于是序列77
33 69 51 确定好了,而这时候线段树恰好可以很快的满足这个查询第几个空位的操作。具体策略是:
1.初试化每个区间的长度为该区间剩下的空位 。
2.每条信息进来后与首先该区间自减1,因为这时候这个数要插入,
3.然后与该节点的左孩子比较空位,如果左孩子空位>=这条信息空位,那么直接进入左孩子。反之进入右孩子,进入右孩子的时候需要需要减掉左孩子(具体参见代码)。
这道题写线段树是很简单的操作,但是最重要的是思路,因为很难想到。因为是插队插入的,所以换个方向思考,最后插入的一定是该位置,然后忽略该位置,后面同理。
主要思路:
现在看样例这组数据,因为上面已经说过了,所以我们先要把所有的输入存储起来,于是从最后一条输入来看,3 69(位置先自加1)说明了前面是有2个空位的,于是这时候就要插入到第3个位置中(原因在于此时序列中没有其他数字,所以在第三个位置),然后进来2 33 现在这条数据在第二个空位那里,然后最关键的一条数据 2 51 ,这条数据进来后发现它应该在第二个空位里面,这时候我们看这条序列_ 33 69 _,这时候第二个空位是69之后的位置,所以此时的序列为_ 33 69 51,最后一条信息1 77进来后此时应该放在第一个空位上,于是序列77
33 69 51 确定好了,而这时候线段树恰好可以很快的满足这个查询第几个空位的操作。具体策略是:
1.初试化每个区间的长度为该区间剩下的空位 。
2.每条信息进来后与首先该区间自减1,因为这时候这个数要插入,
3.然后与该节点的左孩子比较空位,如果左孩子空位>=这条信息空位,那么直接进入左孩子。反之进入右孩子,进入右孩子的时候需要需要减掉左孩子(具体参见代码)。
#include<iostream> #include<fstream> #include<string> #define Lchild rt<<1,L,m #define Rchild rt<<1|1,m+1,R using namespace std; #define maxn 222222 int tree[maxn*3]; int N; int ans[maxn]; int t; struct node { int val; int pos; }; node num[maxn]; void build(int rt = 1, int L = 1, int R = N) { tree[rt] = R - L + 1; if (L == R) return; int m = (L + R) >> 1; build(Lchild); build(Rchild); } void update(int val,int pos, int rt = 1, int L = 1, int R = N) { tree[rt]--; if (L == R) { ans[L] = val; return; } int m = (L + R) >> 1; if (tree[rt << 1] >= pos) update(val, pos, Lchild); else { pos -= tree[rt << 1]; update(val, pos, Rchild); } } int main() { while (scanf_s("%d", &N) != EOF) { t = N; build(); int pos, val; for (int i = 1; i <= N; i++) { scanf_s("%d%d", &pos, &val); pos++; num[i].pos = pos; num[i].val = val; } for (int i = N; i >= 1; i--) { update(num[i].val, num[i].pos); } printf("%d", ans[1]); for (int i = 2; i <=N; i++) { printf(" %d", ans[i]); } printf("\n"); } }
相关文章推荐
- 设计模式之适配器模式
- 叉积判断点在多边形内外 & poj2318
- 关于打印浮点数的一个问题
- C#软件开发实例.私人订制自己的屏幕截图工具(十)在截图中包含鼠标指针形状
- hdu 1051-Wooden Sticks
- 代码中特殊的注释技术——TODO、FIXME和XXX的用处
- 春暖花会开
- java三元运算a?b:c(2015年9月20日)
- usaco Riding the Fences
- git pull冲突解决
- Cache-control
- hadoop中NameNode、DataNode、Secondary、NameNode、JobTracker TaskTracker介绍
- C#软件开发实例.私人订制自己的屏幕截图工具(九)使用自定义光标,QQ截图时的光标
- css中单位px、pt、em和rem的区别
- poj1061-青蛙的约会(扩展欧几里德算法)
- 如何在CSDN博客中所贴的代码进行【代码块】显示
- TCP客户/服务器程序示例
- win10提示 磁盘包含不是“PARTITION_BASIC_DATA_GUID"类型的分区
- Android 之Adapter
- 换个格式输出整数