hdoj 5919 Sequence II 【主席树】

来源:互联网 发布:卖血哥玩的软件是什么 编辑:程序博客网 时间:2024/05/29 09:29

hdoj 5919 Sequence II

题意:给定N个整数,Q次查询,每次查询给定一个区间[L,R],你需要找到区间里面所有元素在该区间第一次出现的位置Pi,将P[]排序去重后,输出第k2元素在原序列的位置。

因为需要的是每个元素在区间里面第一次出现的位置信息,我们可以倒着建立主席树,建立的过程中我们只留下第一次出现的元素。之后用主席树求出区间不同元素个数k,那样的话对于区间[L,R]而言,就是找到以root[l]为根的线段树里面第k2个元素。

#include <cstdio>#include <cstring>#include <map>#include <algorithm>using namespace std;typedef long long LL;const int MAXN = 2e5 + 100;int a[MAXN], b[MAXN];struct Tree {    int sum;    int lson, rson;};Tree tree[MAXN * 40];int root[MAXN], id;void PushUp(int o) {    tree[o].sum = tree[tree[o].lson].sum + tree[tree[o].rson].sum;}int Newnode(LL s, int l, int r) {    ++id;    tree[id].sum = s;    tree[id].lson = l;    tree[id].rson = r;    return id;}void Build(int &o, int l, int r) {    o = Newnode(0, 0, 0);    if(l == r) return ;    int mid = l + r >> 1;    Build(tree[o].lson, l, mid);    Build(tree[o].rson, mid + 1, r);    PushUp(o);}void Update(int &o, int preo, int pos, int l, int r, int val) {    o = Newnode(tree[preo].sum, tree[preo].lson, tree[preo].rson);    if(l == r) {        tree[o].sum += val;        return ;    }    int mid = l + r >> 1;    if(pos <= mid) {        Update(tree[o].lson, tree[preo].lson, pos, l, mid, val);    }    else {        Update(tree[o].rson, tree[preo].rson, pos, mid + 1, r, val);    }    PushUp(o);}int Query_kth(int o, int l, int r, int k) {    if(l == r) return l;    int mid = l + r >> 1;    if(k <= tree[tree[o].lson].sum) {        return Query_kth(tree[o].lson, l, mid, k);    }    else {        return Query_kth(tree[o].rson, mid + 1, r, k - tree[tree[o].lson].sum);    }}int Query_num(int o, int L, int R, int l, int r) {    if(L == l && R == r) return tree[o].sum;    int mid = l + r >> 1;    if(R <= mid) {        return Query_num(tree[o].lson, L, R, l, mid);    }    else if(L > mid) {        return Query_num(tree[o].rson, L, R, mid + 1, r);    }    else {        return Query_num(tree[o].lson, L, mid, l, mid) +               Query_num(tree[o].rson, mid + 1, R, mid + 1, r);    }}int fp[MAXN];int ans[MAXN];int main(){    int t, kcase = 1; scanf("%d", &t);    while(t--) {        int n, q; scanf("%d%d", &n, &q);        for(int i = 1; i <= n; i++) {            scanf("%d", &a[i]);        }        memset(fp, 0, sizeof(fp));        id = 0; Build(root[n + 1], 1, n);        for(int i = n; i >= 1; i--) {            int pos = fp[a[i]];            if(pos == 0) {                Update(root[i], root[i + 1], i, 1, n, 1);            }            else {                int T;                Update(T, root[i + 1], pos, 1, n, -1);                Update(root[i], T, i, 1, n, 1);            }            fp[a[i]] = i;        }        ans[0] = 0;        for(int i = 1; i <= q; i++) {            int l, r; scanf("%d%d", &l ,&r);            int x = (l + ans[i - 1]) % n + 1;            int y = (r + ans[i - 1]) % n + 1;            l = min(x, y); r = max(x, y);            int k = Query_num(root[l], l, r, 1, n);            if(k & 1) {                k = k / 2 + 1;            }            else {                k /= 2;            }            ans[i] = Query_kth(root[l], 1, n, k);        }        printf("Case #%d:", kcase++);        for(int i = 1; i <= q; i++) {            printf(" %d", ans[i]);        }        printf("\n");    }    return 0;}
0 0