HDU5919 Sequence II (主席樹)

題意

給出一個序列,問區間[l, r]中所有不同元素出現的第一個位置(取最左)組成的序列中的中位數。

題解

如果我們從後往前的話在當前位置i我們在主席樹上i這個位置加1,在它之前出現的位置減1,然後我們在主席樹詢問區間的時候每個數都只出現一次了。

查詢[l, r]的時候,查詢第l個版本的主席樹就好,複雜度O(nlogn)。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <string.h>
#include <string>
#include <queue>
#include <set>
using namespace std;
//ios_base::sync_with_stdio(false);
//#include <bits/stdc++.h>
typedef long long ll;

#define maxn 200010
int root[maxn], tot;
struct seg {
    int lson, rson, val;
} T[maxn * 40];
void update(int l, int r, int &now, int pre, int i, int val)
{
    int tmp = now;
    now = ++tot;
    T[now] = tmp ? T[tmp] : T[pre];
    T[now].val += val;

    if(l == r) return ;
    int m = (l + r) >> 1;
    if(i <= m) update(l, m, T[now].lson, T[pre].lson, i, val);
    else update(m + 1, r, T[now].rson, T[pre].rson, i, val);
}
int query(int l, int r, int now, int K)
{
    if(l == r) return r;
    int m = (l + r) >> 1;
    if(T[T[now].lson].val >= K)
        return query(l, m, T[now].lson, K);
    else
        return query(m + 1, r, T[now].rson, K - T[T[now].lson].val);
}
int getsum(int l, int r, int now, int L, int R)
{
    if(L <= l && r <= R) return T[now].val;
    int m = (l + r) >> 1, ret = 0;
    if(L <= m) ret += getsum(l, m, T[now].lson, L, R);
    if(R > m) ret += getsum(m + 1, r, T[now].rson, L, R);
    return ret;
}
int a[maxn], p[maxn], ans[maxn];
int main()
{
    int t, kase = 0;
    cin >> t;
    while(t--)
    {
        int n, m;
        cin >> n >> m;

        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(int i = n; i >= 1; i--)
        {
            if(p[a[i]]) update(1, n, root[i], root[i+1], p[a[i]], -1);
            update(1, n, root[i], root[i+1], i, 1);
            p[a[i]] = i;
        }
        ans[0] = 0;
        for(int i = 0, l, r, sum; i < m; i++)
        {
            if(i)
                ans[i] = ans[i-1];
            scanf("%d%d", &l, &r);
            l = (l + ans[i]) % n + 1;
            r = (r + ans[i]) % n + 1;
            if(l > r) swap(l, r);
            sum = getsum(1, n, root[l], l, r);
            sum = sum / 2 + sum % 2;
            ans[i] = query(1, n, root[l], sum);
        }
        printf("Case #%d:", ++kase);
        for(int i = 0; i < m; i++)
            printf(" %d", ans[i]);
        printf("\n");
        while(tot)
        {
            T[tot].lson = T[tot].rson = 0;
            T[tot--].val = 0;
        }
        for(int i = 1; i <= n; i++)
        {
            root[i] = 0;
            p[a[i]] = 0;
        }
        tot = 0;
    }
    return 0;
}

 

發佈了84 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章