HDU 4006 POJ 2828 线段树(排列/找有序位置)
来源:互联网 发布:金山软件 港股 编辑:程序博客网 时间:2024/05/16 01:16
又是一年一度的暑假集训 然而前几天刚做完搜索 还木有做明白 现在就跑过来做线段树 唉 不知道我这个弱弱什么时候才能变得不那么弱~
HDU 4006 与 POJ 2828 两题相类似
HDU 4006 是找第K大的数 POJ 2828是把数字插入到指定位置然后输出arry 两题都属于线段树单点更新的问题
HDU 4006
tree[root].sum 记录该节点一共有多少个数字 若目前出现的数字为cnt 在Query时查询第 cnt-k+1 就好了
需要注意的问题是 n 表示操作数目 所以建树的时候要注意 在此处本弱弱WA了好几次- -||
下面是ac代码
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1001000;int n,k;struct tree{ int l,r,sum;}tree[maxn*4];void PushUp(int root){ tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;}void Build(int root,int l,int r){ tree[root].l = l; tree[root].r = r; if(tree[root].l == tree[root].r) { tree[root].sum = 0; return ; } int mid = (tree[root].l + tree[root].r)/2; Build(root<<1,l,mid); Build(root<<1|1,mid+1,r); PushUp(root);}void Update(int root,int num){ if(tree[root].l == tree[root].r) { tree[root].sum ++; return ; } int mid = (tree[root].l + tree[root].r)/2; if(num <= mid) Update(root<<1,num); if(num > mid) Update(root<<1|1,num); PushUp(root);}int Query(int root,int pos){ if(tree[root].l == tree[root].r) { return tree[root].l; } int ret; if(pos <= tree[root<<1].sum) //tree[root<<1].sum 表示lson所含数的个数 若查询pos大的数 是否在lson内 若不在则查询rson的pos-tree[root<<1].sum大的数 这好好理解一下就行了 POJ 2828 也主要运用这个 ret = Query(root<<1,pos); else //(pos > tree[root<<1].sum) ret = Query(root<<1|1,pos-tree[root<<1].sum); return ret;}int main(){ while(~scanf("%d%d",&n,&k)) { Build(1,1,maxn); char str[2]; int cnt = 0,num; while(n--) { scanf("%s",str); if(str[0] == 'I') { scanf("%d",&num); Update(1,num); cnt ++; } if(str[0] == 'Q') { int ans = Query(1,cnt-k+1); cout<<ans<<endl; } } } return 0;}
POJ 2828
题意 给出 posi vali 顺序插入数字 再输出结果 大家看hint就应该能明白
思路和上题差不多
不同的是逆序进行插入 因为正序进行的话 前面的会影响后面的位置 所以逆序进行就可以解决这个问题
每个节点存的是还有多少空位置 1 为有数字 0 为空
pos位在lson内找不到 则在rson找(pos-lson.sum)位
赘述一下 插入相同位置的问题 假如说
2 3
2 5
0 1
1 2
output 1 2 5 3
这组数据 两个数 3和5都插在2位置上面,我们逆序进行插入 先插入的是5 后插的是3 当插入3的时候 询问(0,1,2)作为lson的父节点时候 lson.sum = 0已经没有位置可插入了所以 3 自然就插入到 rson的第一个位置(pos-lson.sum)这样就解决插入同一个位置的问题了哈~
#include <iostream>#include <cstdio>#include <cmath>#define maxn 200005using namespace std;int seq[maxn];struct tree{ int l,r,sp;}tree[maxn*4];int n,p[maxn],v[maxn];void BuildTree(int root,int l,int r){ tree[root].l = l; tree[root].r = r; if(tree[root].l == tree[root].r) { tree[root].sp = 1; return ; } int mid = (tree[root].l+tree[root].r)/2; BuildTree(root<<1,l,mid); BuildTree(root<<1|1,mid+1,r); tree[root].sp = tree[root<<1].sp+tree[root<<1|1].sp;}void update(int root,int l,int r,int pos,int val){ if(tree[root].l == tree[root].r) { seq[tree[root].l] = val; tree[root].sp = 0; return; } int mid = (tree[root].l + tree[root].r)/2; if(tree[root<<1].sp >= pos) update(root<<1,l,mid,pos,val); else update(root<<1|1,mid+1,r,pos-tree[root<<1].sp,val); tree[root].sp = tree[root<<1].sp+tree[root<<1|1].sp;}int main(){ while(~scanf("%d",&n)) { BuildTree(1,1,n); for(int i = 1;i <= n;i ++) scanf("%d%d",&p[i],&v[i]); //nixu for(int i = n;i >= 1;i --) update(1,1,n,p[i]+1,v[i]); for(int i = 1;i <= n;i ++) printf("%d ",seq[i]); printf("\n"); } return 0;}
如有疏漏 还请各位指出啊~
0 0
- HDU 4006 POJ 2828 线段树(排列/找有序位置)
- HDU 2852 线段树(查询有序位置)
- POJ - 2828 - Buy Tickets(线段树-单点更新找位置)
- hdu 2019 排列有序
- HDU 5239 Doom 线段树+找规律
- poj 2828 Buy Tickets (线段树 单节点 查询位置更新)
- poj~2828(线段树)
- poj 2828(线段树)
- POJ--2828(线段树)
- poj 2828 Buy Tickets(树状数组找部分和为k的第一个位置)
- HDU 1281 棋盘游戏 (枚举+匈牙利找关键位置)
- hdu 2795 Billboard (线段树,优先找满足条件的坐标较小的)
- HDU 1542 && POJ 1151 Atlantis(线段树+扫描线)
- poj 1151 hdu 1542 atlantis (线段树+扫描线)
- poj 1151 & hdu 1542 Atlantis(线段树,扫描线)
- [HDU 1394]求全排列逆序数最大值[线段树]
- hdu 5737【线段树+有序表+线段树小技巧+ 二分不要写错……】
- POJ 2828 (线段树)
- Thinkphp 3.2命名空间版如何使用PHPExcel导入Excel文件
- 设备管理(3.5)------嵌入式系统软件及操作系统知识
- Improving the GPA
- 《啪啪三国》技术详解
- 初涉canvas
- HDU 4006 POJ 2828 线段树(排列/找有序位置)
- android DDMS 导出files文件夹下的容时报错
- C++ STL遍历map的时候如何删除其中的element
- 理解Python中的With语句
- Input设备驱动之事件类型
- 关系模型基本概念
- Android之GridView横向左右滚动
- BlockingQueue
- 深入分析Android (build/core/*.mk脚本)