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 再补……

时间: 2024-08-10 23:30:28

HDU 3436--Queue-jumpers (树状数组 or Splay Tree)的相关文章

HDU 1541 Stars (树状数组)

Problem Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given

HDU 3854 Glorious Array(树状数组)

题意:给一些结点,每个结点是黑色或白色,并有一个权值.定义两个结点之间的距离为两个结点之间结点的最小权值当两个结点异色时,否则距离为无穷大.给出两种操作,一种是将某个结点改变颜色,另一个操作是询问当前距离小于K的结点有多少对,K是一个定值. 思路:先求最初时候小于k的结点有多少对,然后每次改变颜色的时候,统计该点左侧和右侧各有多少同色和异色的结点(这一步使用树状数组),分别处理就行.另外需要预处理离某个结点最近的两个距离小于K的结点的位置. 代码写的略乱. #include<cstdio> #

HDU 2689 Sort it (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2689 Sort it Problem Description You want to processe a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. Then how many times it 

HDU 2492 Ping pong (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Problem Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To improve their skill rank

HDU 1541 Stars(树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 解析: 题意:大概就是计算每颗星星左下边包括了多少颗星星,这个数值就是level.左下边不包括本身,不超过本身的x,y的坐标,可以等于.问每种level有多少颗星星. 这题,一开始想不到怎么用到树状数组,后来看了一下,发现题目给的数据是已经按x,y排好序的,所以我们可以不用管y的值. 注意: 1.每次输入一个坐标对之后,都要计算一下这个它的level. 2.此题的x坐标可以为0,而树状数组是从

HDU 1892 二维树状数组

See you~ Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 3485    Accepted Submission(s): 1103 Problem Description Now I am leaving hust acm. In the past two and half years, I learned so many kno

HDU - 2838 Cow Sorting (树状数组 + 逆序对)

HDU - 2838 Cow Sorting Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" lev

hdu-5493 Queue(二分+树状数组)

题目链接: Queue Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1093    Accepted Submission(s): 566 Problem Description N people numbered from 1 to N are waiting in a bank for service. They all stan

HDU 3874 Necklace(树状数组)

Problem Description Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count