1. 程式人生 > >[POI2014]KUR-Couriers

[POI2014]KUR-Couriers

solution () urn pri 數列 素數 bound 個數 esc

這個題……一開始在掛……\(ORZ\)最終發現是我的主席樹掛了……看來我該退役了\(OTZ\)

#\(\mathcal{\color{red}{Description}}\)

\(\color{cyan}{\mathcal{Link}}\)

給一個數列,每次詢問一個區間內有沒有一個數出現次數超過一半。如果有的話,輸出這個數的數值。

#\(\mathcal{\color{red}{Solution}}\)

這個題好像可以上莫隊……但是我校大佬講莫隊的時候沒有用心聽\(ORZ.\)

於是我們考慮用主席樹\(qwq\) ,而在這裏我們千萬不要忘了主席樹的最基本的功能是,維護一段區間內某個數字的個數

那我們就可以考慮,對於一個區間\(L\)

~ \(R\),我們取樹\(R\)和樹\(L - 1\)作差得到樹\(W\),之後在\(W\)\(1\)~\(Len\)裏面遞歸下去,遞歸的選擇是某個區間的元素個數比區間內元素個數的二分之一要大。假設\(l\)區間內的元素數量比\((qr - ql + 1 )/2\)要大,那麽首先對於區間\(r\)來說,\(r\)肯定不合法,所以向\(l\)區間繼續遞歸下去。如果遞歸時出現左右區間都不滿足,那麽直接\(return\) \(0.\)

il int query(int Left, int Right, int l, int r, int k){
    if (l == r) return l ;
    int
x = sum[L[Right]] - sum[L[Left]], y = sum[R[Right]] - sum[R[Left]] ; if ((x << 1) > k) return query(L[Left], L[Right], l, mid, k) ; if((y << 1) > k) return query(R[Left], R[Right], mid + 1, r, k) ; return 0 ; }

嗯,其實只要明白了主席樹的原理,這個題其實是很水的板子。不過像我這種蒟蒻因為入門的時候學的是區間第\(k\)小,所以忘記了主席樹的基本功能……

#include<cstdio>
#include<iostream>
#include<algorithm>
#define il inline
#define MAXN 500510
#define mid ((l + r) >> 1)

using namespace std ;
int a, b, c ;
int pos, N, base[MAXN], aft[MAXN], M, i ;
int cnt, Len, T[MAXN << 5], L[MAXN << 5], R[MAXN << 5], sum[MAXN << 5] ;

il int qr(){
    int k = 0, f = 1; 
    char c = getchar() ;
    while(!isdigit(c)){
        if (c == ‘-‘) f = -1 ;
        c = getchar() ;
    }
    while(isdigit(c)){
        k = (k << 1) + (k << 3) + c - 48 ;
        c = getchar() ;
    } 
    return k * f;
}
il int build(int l, int r){
    int rt = ++ cnt ;
    sum[rt] = 0 ;
    if(l < r){
        L[rt] = build(l, mid) ;
        R[rt] = build(mid + 1, r) ;
    }
    return rt;
}
il int update(int last, int l, int r, int x){
    int rt = ++ cnt ;
    sum[rt] = sum[last] + 1 ;
    R[rt] = R[last] ;
    L[rt] = L[last] ;
    if (l < r){
        if (x <= mid) L[rt] = update(L[last], l, mid, x) ;
        else  R[rt] = update(R[last], mid + 1, r, x) ;
    }
    return rt ;
}
il int query(int Left, int Right, int l, int r, int k){
    if (l == r) return l ;
    int x = sum[L[Right]] - sum[L[Left]], y = sum[R[Right]] - sum[R[Left]] ;
    if ((x << 1) > k) return query(L[Left], L[Right], l, mid, k) ;
    if((y << 1) > k) return query(R[Left], R[Right], mid + 1, r, k) ;
    return 0 ;
}
int main(){
    cin >> N >> M;
    for(i = 1; i <= N; i ++){
        base[i] = qr() ;
        aft[i] = base[i] ;
    }
    sort(aft + 1, aft + N + 1) ;
    Len = unique(aft + 1, aft + N + 1) - (aft + 1) ; 
    T[0] = build(1, Len) ;
    for(i = 1; i <= N; i ++){
        pos = lower_bound(aft + 1, aft + Len + 1, base[i]) - aft;
        T[i] = update(T[i - 1], 1, Len, pos) ;
    }
    for(i = 1; i <= M; i ++){
        a = qr(), b = qr() ;
        printf("%d\n", query(T[a - 1], T[b], 1, Len, b - a + 1)) ;
    }
}

還有,千萬不要寫錯變量啊!!比如\(Len\)\(N\)搞混了之類的\(QAQ\)

[POI2014]KUR-Couriers