CF765Fお土産セグメントツリー

ポータル


不滅のタイトル

オフラインおよび列挙は、それぞれの位置を維持するために、右端を要求されます(私は\)\した後、すべての位置で\(J \)の間隔の最小値から、次いで分を採取します。このようなアプローチの最悪の複雑さは明らかである(O(N ^ 2)\ \) 、我々はいくつかの剪定を必要としています。

我々はのための場所を検討し\(私は\)された後、実際のは、どのような位置の最小値を更新する可能性があります。シーケンスと仮定\(\ {\}は\ ) 増加するシーケンスである、\(A_1> I、val_ A_1} {\ GEQ val_i \)特定の点取る権利、前記各時刻\(a_jを\)場合\(I \)最小位置更新が有効になり、それが満たされるであろう:\(。\ FORALL J \ [1、| |)、| val_i - val_ a_j {} | \ GEQ 2 | val_i - val_ + J. 1 A_ {{}} | \) この条件が満たされない場合ので、その後\(a_j \)\(A_ {J + 1} \) の距離が、この時間に小さくなる\(私は\ )更新が無効です。

上記見つけるのは難しいことではありません\(\)の配列の長さは唯一の最大必要があります\(ログ10 ^ 9 \)キーを、私たちはどのような位置にする場合、変更する必要性への権利のポイントを見つけるためにツリーラインを使用することができます\を(私は\ )の位置は、その後、更新するために、右にポイントを移動し、統計が答えます。複雑\(O(nlog ^ 2N + qlogn)\)

#include<bits/stdc++.h>
using namespace std;

int read(){
    int a = 0; char c = getchar(); bool f = 0;
    while(!isdigit(c)){f = c == '-'; c = getchar();}
    while(isdigit(c)){
        a = a * 10 + c - 48; c = getchar();
    }
    return f ? -a : a;
}

const int _ = 3e5 + 7;
int cnt , N , M , arr[_] , lsh[_] , id[_] , L[_] , R[_] , ans[_]; vector < int > Q[_] , pos[_];

namespace segt{
    int mn[_ << 2];

#define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1)
    
    void clear(){memset(mn , 0x3f , sizeof(mn));}
    
    void modify(int x , int l , int r , int tar , int val){
        mn[x] = min(mn[x] , val); if(l == r) return;
        mid >= tar ? modify(lch , l , mid , tar , val) : modify(rch , mid + 1 , r , tar , val);
    }
    
    int qry(int x , int l , int r , int L , int R){
        if(l >= L && r <= R) return mn[x];
        int mn = 1e9;
        if(mid >= L) mn = qry(lch , l , mid , L , R);
        if(mid < R) mn = min(mn , qry(rch , mid + 1 , r , L , R));
        return mn;
    }
}using namespace segt;

int main(){
    N = read(); segt::clear(); for(int i = 1 ; i <= N ; ++i) arr[i] = lsh[i] = read();
    M = read(); for(int i = 1 ; i <= M ; ++i){L[i] = read(); R[i] = read(); Q[R[i]].push_back(i);}
    sort(lsh + 1 , lsh + N + 1); cnt = unique(lsh + 1 , lsh + N + 1) - lsh - 1;
    for(int i = 1 ; i <= N ; ++i) id[i] = lower_bound(lsh + 1 , lsh + cnt + 1 , arr[i]) - lsh;
    for(int i = N , cur , t ; i ; --i){
        cur = cnt;
        while((t = segt::qry(1 , 1 , cnt , id[i] , cur)) <= N){
            pos[t].push_back(i); if(id[t] == id[i]) break;
            cur = upper_bound(lsh + 1 , lsh + cnt + 1 , (arr[i] + arr[t]) / 2) - lsh - 1;
        }
        cur = 1;
        while((t = segt::qry(1 , 1 , cnt , cur , id[i])) <= N){
            pos[t].push_back(i); if(id[t] == id[i]) break;
            cur = lower_bound(lsh + 1 , lsh + cnt + 1 , (arr[i] + arr[t] + 1) / 2) - lsh;
        }
        segt::modify(1 , 1 , cnt , id[i] , i);
    }
    segt::clear();
    for(int i = 1 ; i <= N ; ++i){
        for(auto t : pos[i]) segt::modify(1 , 1 , N , t , abs(arr[i] - arr[t]));
        for(auto t : Q[i]) ans[t] = segt::qry(1 , 1 , N , L[t] , i);
    }
    for(int i = 1 ; i <= M ; ++i) printf("%d\n" , ans[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Itst/p/11527929.html
おすすめ