CodeForces 840D Destiny【主席樹】

題目大意:

有一個長度爲nn的序列,有mm次詢問,每次詢問區間[L,R][L,R]中出現次數 嚴格大於 區間長度除以kk(即 RL+1K\frac{R-L+1}{K})的元素中,最小的那個數是多少。若不存在這樣的元素輸出-1。

N,M3105N,M≤3∗10^5K5K≤5

題解

用一個數組存數字(離散化一次)的出現次數,在其上建主席樹。向下詢問時值小於指定值時返回

  • 這樣至多隻會訪問K個葉子節點(不可能一段區間裏面出現超過K個數值個數大於 區間長度/K 的)。K很小,所以可以去枚舉。
  • 有一點可以優化就是如果左節點找到答案就不用去搜索右節點了








#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define maxn 300010
using namespace std;

const int M = maxn * 30;
int n,q,m,tot,ans;
int a[maxn], t[maxn];
int T[maxn], lson[M], rson[M], c[M];
void Init_hash(){
    for(int i=1;i<=n;i++)
        t[i] = a[i];
    sort(t+1,t+1+n);
    m = (int)(unique(t+1, t+1+n)-t-1);
}

int build(int l, int r)
{
    int root = tot++;
    c[root] = 0;
    if(l!=r){
        int mid = (l+r)>>1;
        lson[root] = build(l, mid);
        rson[root] = build(mid+1,r);
    }
    return root;
}

int mapp(int x){
    return (int)(lower_bound(t+1, t+1+m, x) - t);
}

int update(int root, int pos, int val){
    int newroot = tot++, tmp = newroot;
    c[newroot] = c[root] + val;
    int l = 1, r = m;
    while(l < r){
        int mid = (l+r)>>1;
        if(pos<=mid){
            lson[newroot] = tot++; rson[newroot] = rson[root];
            newroot = lson[newroot]; root = lson[root];
            r = mid;
        }
        else{
            rson[newroot] = tot++; lson[newroot] = lson[root];
            newroot = rson[newroot]; root = rson[root];
            l = mid+1;
        }
        c[newroot] = c[root] + val;
    }
    return tmp;
}

void query(int left_root, int right_root, int l, int r, int k){
    if(c[right_root]-c[left_root] < k) return;
    if(l==r){
        if(c[right_root]-c[left_root] >= k) ans = min(ans, l);
        return;
    }
    int mid = (l+r)>>1;
    query(lson[left_root], lson[right_root], l, mid, k);
    if(ans==0x3f3f3f3f) query(rson[left_root], rson[right_root], mid+1, r, k);
}

int main()
{
        tot = 0;
        scanf("%d %d", &n, &q);
        for(int i=1;i<=n;i++)
            scanf("%d", &a[i]);
        Init_hash();
        T[0] = build(1, m);
        for(int i=1;i<=n;i++){
            int pos = mapp(a[i]);
            T[i] = update(T[i-1], pos, 1);
        }
        while(q--){
            ans = 0x3f3f3f3f;
            int l, r, k;
            scanf("%d%d%d", &l, &r, &k);
            int v = (r-l+1)/k + 1;
            query(T[l-1], T[r], 1, m, v);
            if(ans==0x3f3f3f3f) puts("-1");
            else printf("%d\n", t[ans]);
        }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章