1. 程式人生 > >BZOJ3489 A simple rmq problem K-D Tree

BZOJ3489 A simple rmq problem K-D Tree

return written char zoj str turn spa tst 最大值

傳送門


什麽可持久化樹套樹才不會寫呢,K-D Tree大法吼啊

對於第\(i\)個數,設其前面最後的與它值相同的位置為\(pre_i\),其後面最前的與它值相同的位置為\(aft_i\),那麽對於一個詢問\((l,r)\)和一個位置\(i\),需要同時滿足\(pre_i < l \leq i \leq r < aft_i\)時,第\(i\)個位置的值才能產生貢獻。

\((pre_i , i , aft_i)\)看作三維空間中的一個點,那麽能夠產生貢獻的一些點就會在一個立方體範圍內。使用K-D Tree進行搜索即可。

記得要加一些剪枝,比如當前訪問的區域的最大值比當前答案小就退出等

記得一定不要把nth_element(n + l , n + mid , n + r + 1)寫成nth_elemet(n + l , n + r + 1 , n + mid)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
//This code is written by Itst
using namespace std;

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

const int MAXN = 1e5 + 7;
struct node{
    int pos[3] , val;
}nd[MAXN];
int N , M , lastans , ind[MAXN];
int pre[MAXN] , ch[MAXN][2] , maxV[MAXN] , maxP[MAXN][3] , minP[MAXN][3];

bool cmp0(node a , node b){return a.pos[0] < b.pos[0];}
bool cmp1(node a , node b){return a.pos[1] < b.pos[1];}
bool cmp2(node a , node b){return a.pos[2] < b.pos[2];}

inline int pushup(int x){
    memcpy(maxP[x] , nd[x].pos , sizeof(nd[x].pos));
    memcpy(minP[x] , nd[x].pos , sizeof(nd[x].pos));
    maxV[x] = nd[x].val;
    for(int p = 0 ; p < 2 ; ++p)
    if(ch[x][p]){
        maxV[x] = max(maxV[x] , maxV[ch[x][p]]);
        for(int i = 0 ; i < 3 ; ++i){
        maxP[x][i] = max(maxP[x][i] , maxP[ch[x][p]][i]);
        minP[x][i] = min(minP[x][i] , minP[ch[x][p]][i]);
        }
    }
    return x;
}

int build(int l , int r , int tp){
    if(l > r) return 0;
    if(l == r) return pushup(l);
    int mid = (l + r) >> 1;
    nth_element(nd + l , nd + mid , nd + r + 1 , tp == 0 ? cmp0 : (tp == 1 ? cmp1 : cmp2));
    ch[mid][0] = build(l , mid - 1 , (tp + 1) % 3);
    ch[mid][1] = build(mid + 1 , r , (tp + 1) % 3);
    return pushup(mid);
}

long long cnt;
void query(int cur , int a , int b){
    if(minP[cur][0] >= a || maxP[cur][2] <= b || minP[cur][1] > b || maxP[cur][1] < a || maxV[cur] <= lastans) return;
    if(maxP[cur][0] < a && minP[cur][2] > b && minP[cur][1] >= a && maxP[cur][1] <= b){
    lastans = maxV[cur]; return;
    }
    if(nd[cur].pos[0] < a && nd[cur].pos[1] >= a && nd[cur].pos[1] <= b && nd[cur].pos[2] > b)
    lastans = max(lastans , nd[cur].val);
    query(ch[cur][0] , a , b); query(ch[cur][1] , a , b);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    N = read(); M = read();
    for(int i = 1 ; i <= N ; ++i){
    nd[i].pos[1] = i;
    int a = nd[i].val = read();
    nd[i].pos[0] = pre[a]; nd[pre[a]].pos[2] = i;
    pre[a] = i;
    }
    for(int i = 1 ; i <= N ; ++i)
    nd[pre[i]].pos[2] = N + 1;
    int rt = build(1 , N , 0);
    while(M--){
    int x = (read() + lastans) % N + 1 , y = (read() + lastans) % N + 1;
    if(x > y) x ^= y ^= x ^= y;
    lastans = 0;
    query(rt , x , y);
    printf("%d\n" , lastans);
    }
    return 0;
}

BZOJ3489 A simple rmq problem K-D Tree