poj 2828 Buy Tickets(树状数组 | 线段树)

题目链接:poj 2828 Buy Tickets

题目大意:给定N,表示有个人,给定每一个人站入的位置,以及这个人的权值,如今按队列的顺序输出每一个人的权值。

解题思路:第K大元素,非常巧妙,将人入队的顺序倒过来看,就是纯第K大问题,然后用树状数组还是线段树就都能够做了。

 
  
C++ 线段树
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200005; #define lson(x) ((x)<<1) #define rson(x) (((x)<<1)+1) struct Node { int l, r, s; void set(int l, int r, int s) { this->l = l; this->r = r; this->s = s; } }nd[maxn * 4]; int N, val[maxn], pos[maxn], rec[maxn]; void build (int u, int l, int r) { nd[u].set(l, r, r - l + 1); if (l == r) return ; int mid = (l + r) / 2; build(lson(u), l, mid); build(rson(u), mid + 1, r); } int query (int u, int x) { nd[u].s--; if (nd[u].l == nd[u].r) return nd[u].l; if (nd[lson(u)].s >= x) return query(lson(u), x); else return query(rson(u), x - nd[lson(u)].s); } int main () { while (scanf("%d", &N) == 1) { build(1, 0, N - 1); for (int i = 0; i < N; i++) scanf("%d%d", &pos[i], &val[i]); for (int i = N - 1; i >= 0; i--) rec[query(1, pos[i] + 1)] = i; printf("%d", val[rec[0]]); for (int i = 1; i < N; i++) printf(" %d", val[rec[i]]); printf("\n"); } return 0; }
 
  
C++ 树状数组
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200005; #define lowbit(x) ((x)&(-x)) int N, fenw[maxn], pos[maxn], val[maxn], rec[maxn]; void add (int x, int v) { while (x <= N) { fenw[x] += v; x += lowbit(x); } } int find (int x) { int p = 0, s = 0; for (int i = 20; i >= 0; i--) { p += (1<<i); if (p > N || s + fenw[p] >= x) p -= (1<<i); else s += fenw[p]; } return p + 1; } int main () { while (scanf("%d", &N) == 1) { memset(fenw, 0, sizeof(fenw)); for (int i = 1; i <= N; i++) { add(i, 1); scanf("%d%d", &pos[i], &val[i]); } for (int i = N; i; i--) { int tmp = find(pos[i] + 1); rec[tmp] = i; add(tmp, -1); } for (int i = 1; i <= N; i++) printf("%d%c", val[rec[i]], i == N ? '\n' : ' '); } return 0; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
POJ 2182是一道使用树状数组解决的题目,题目要求对给定的n个数进行排序,并且输出每个数在排序后的相对位置。树状数组是一种用来高效处理前缀和问题的数据结构。 根据引用中的描述,我们可以通过遍历数组a,对于每个元素a[i],可以使用二分查找找到a到a[i-1]中小于a[i]的数的个数。这个个数就是它在排序后的相对位置。 代码中的query函数用来求前缀和,add函数用来更新树状数组。在主函数中,我们从后往前遍历数组a,通过二分查找找到每个元素在排序后的相对位置,并将结果存入ans数组中。 最后,我们按顺序输出ans数组的元素即可得到排序后的相对位置。 参考代码如下: ```C++ #include <iostream> #include <cstdio> using namespace std; int n, a += y; } } int main() { scanf("%d", &n); f = 1; for (int i = 2; i <= n; i++) { scanf("%d", &a[i]); f[i = i & -i; } for (int i = n; i >= 1; i--) { int l = 1, r = n; while (l <= r) { int mid = (l + r) / 2; int k = query(mid - 1); if (a[i > k) { l = mid + 1; } else if (a[i < k) { r = mid - 1; } else { while (b[mid]) { mid++; } ans[i = mid; b[mid = true; add(mid, -1); break; } } } for (int i = 1; i <= n; i++) { printf("%d\n", ans[i]); } return 0; } ``` 这段代码使用了树状数组来完成题目要求的排序功能,其中query函数用来求前缀和,add函数用来更新树状数组。在主函数中,我们从后往前遍历数组a,通过二分查找找到每个元素在排序后的相对位置,并将结果存入ans数组中。最后,我们按顺序输出ans数组的元素即可得到排序后的相对位置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [poj2182Lost Cows——树状数组快速查找](https://blog.csdn.net/aodan5477/article/details/102045839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [poj_2182 线段树/树状数组](https://blog.csdn.net/weixin_34138139/article/details/86389799)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值