CF765F Souvenirs segment tree

Portal


Immortal title

Offline and Enumeration will ask the right end, to maintain a position of each \ (I \) in all its positions after the \ (J \) from the minimum value of the interval is then taken min. Worst complexity of such an approach is apparently \ (O (n ^ 2) \) , we need some pruning.

We consider a location for a \ (i \) , after which the real is likely to update the minimum of what position. Assuming that the sequence \ (\ {a \} \ ) is an increasing sequence, \ (A_1> I, val_ A_1} {\ GEQ val_i \) , and wherein each time the right to take a certain point \ (a_j \) when \ (I \) minimum location update will be effective, it would be met: \ (\ FORALL J \ in [. 1, | a |), | val_i - val_ a_j {} | \ GEQ 2 | val_i - val_ + J. 1 A_ {{}} | \) , because if this condition is not satisfied then the \ (a_j \) and \ (a_ {j + 1} \) distance will be smaller at this time \ (I \ ) update is invalid.

Not difficult to find the above \ (a \) the length of the sequence will only have a maximum of \ (log 10 ^ 9 \) key, so we can use the tree line to find out what the position when the right point to the need to modify \ (i \ ) position, then move the right point to update and statistics answer. Complexity \ (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;
}

Guess you like

Origin www.cnblogs.com/Itst/p/11527929.html