HDU 3436--Queue-jumpers (树状数组 or Splay Tree)
Posted 我不吃饼干呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3436--Queue-jumpers (树状数组 or Splay Tree)相关的知识,希望对你有一定的参考价值。
树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html
树状数组求前缀和大于等于k的最大值,第一次看到这种方法,很神奇,就是没看懂= =
二分也是可以求的,不过感觉会慢一些……
思路就是把所有没有询问到的数压缩
例如如果n等于10 值询问到了 2, 7 大概是这样的
【1,2】【3,4,5,6,7】【8,9,10】
1 2 3
分成3块,最多分为q块,实现离散化。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 200005; int op[N], a[N], b[N], p[N], no[N]; int n, q; struct BIT { int arr[N]; int n; int sum(int p) { int ans = 0; while (p) { ans += arr[p]; p -= lowbit(p); } return ans; } void add(int p, int v) { while (p <= n) { arr[p] += v; p += lowbit(p); } } int find(int k) { //在数组中找第一个大于等于k的位置 int pos = 0, cnt = 0; for (int i = 17; i >= 0; --i) { pos += (1<<i); if (pos >= n || cnt + arr[pos] >= k) pos -= (1<<i); else cnt += arr[pos]; } return pos+1; } void init(int n) { this->n = n; memset(arr, 0, sizeof arr); } int lowbit(int x) { return x&-x; } } bit; int main() { //freopen("in.txt", "r", stdin); int T, cas = 0; scanf("%d", &T); while (T--) { printf("Case %d:\n", ++cas); scanf("%d%d", &n, &q); char ch[10]; int idx = 0; for (int i = 1; i <= q; ++i) { scanf("%s%d", ch, &a[i]); if (*ch == ‘T‘) op[i] = 1; else if (*ch == ‘Q‘) op[i] = 2; else op[i] = 3; if (op[i] < 3) b[++idx] = a[i]; } b[++idx] = n; sort(b+1, b+1+idx); n = unique(b+1, b+1+idx) - b - 1; bit.init(2*q); for (int i = 1; i <= n; ++i) { bit.add(q+i, b[i]-b[i-1]); no[q+i] = b[i]; // no[i] 数组i处的编号 原编号!! p[i] = q+i; // p[i] 编号为i的位置 } int top = q; for (int i = 1; i <= q; ++i) { if (op[i] == 1) { int x = lower_bound(b+1, b+1+n, a[i]) - b; bit.add(p[x], -1); // 要把x挪到顶端 p[x]位置的数字个数减少一个 no[p[x]]--; // x走了 剩下的是x-1 p[x] = top; // x的位置变成了top bit.add(top, 1); // top位置有一个数字x +1 no[top] = a[i]; top--; } else if (op[i] == 2) { int x = lower_bound(b+1, b+1+n, a[i]) - b; printf("%d\n", bit.sum( p[ x ] )); } else { int pos = bit.find(a[i]); int sp = bit.sum(pos); if (sp == a[i]) printf("%d\n", no[pos]); else printf("%d\n", no[pos]-(sp-a[i])); } } } return 0; }
Splay 再补……
以上是关于HDU 3436--Queue-jumpers (树状数组 or Splay Tree)的主要内容,如果未能解决你的问题,请参考以下文章
BestCoder Round #77 (div.2)(hdu5650,hdu5651(逆元),hdu5652(二分),hdu5653(dp))