bzoj3489

kdtree

3维kdtree,就是三个维度轮换着切,我们把每个元素看成一个点,坐标是上次出现的位置,下次出现的位置,自己的位置,第一个<l,第二个>r,第三个[l,r],然后kdtree上爆搜剪枝就行了。

kdtree看起来能解决所有偏序问题。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, inf = 1e9;
int rd()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n, m, root, d, ans;
int last[N];
struct data {
    int p[3], mn[3], mx[3], lc, rc, ans, val;
    bool friend operator < (const data &a, const data &b) {
        if(a.p[d] != b.p[d]) return a.p[d] < b.p[d];
        if(a.p[(d + 1) % 3] != b.p[(d + 1) % 3]) return a.p[(d + 1) % 3] < b.p[(d + 1) % 3];
        if(a.p[(d + 2) % 3] != b.p[(d + 2) % 3]) return a.p[(d + 2) % 3] < b.p[(d + 2) % 3]; 
    }
} a[N];
void update(int x)
{
    int lc = a[x].lc, rc = a[x].rc;
    for(int i = 0; i < 3; ++i)
    {   
        a[x].mn[i] = min(a[x].p[i], min(a[lc].mn[i], a[rc].mn[i]));
        a[x].mx[i] = max(a[x].p[i], max(a[lc].mx[i], a[rc].mx[i]));  
    }
    a[x].ans = max(a[x].val, max(a[lc].ans, a[rc].ans));
}
int build(int l, int r, int D)
{
    if(l > r) return 0;
    d = D;
    int mid = (l + r) >> 1;
    nth_element(a + l, a + mid, a + r + 1);
    a[mid].lc = build(l, mid - 1, (D + 1) % 3);
    a[mid].rc = build(mid + 1, r, (D + 1) % 3);
    update(mid);
    return mid;
}
bool out(int k, int l, int r)
{
    return ans < a[k].ans && a[k].mn[0] <= r && a[k].mx[0] >= l && a[k].mn[1] < l && a[k].mx[2] > r;
}
void query(int k, int l, int r)
{
    if(!k || !out(k, l, r)) return;
    if(a[k].mx[0] <= r && a[k].mn[0] >= l && a[k].mx[1] < l && a[k].mn[2] > r) 
    {
        ans = max(ans, a[k].ans);
        return;
    }
    if(a[k].p[0] <= r && a[k].p[0] >= l && a[k].p[1] < l && a[k].p[2] > r) ans = max(ans, a[k].val);
    query(a[k].lc, l, r);
    query(a[k].rc, l, r);
}
int main()
{
    for(int i = 0; i < 3; ++i) a[0].mn[i] = inf, a[0].mx[i] = a[0].ans = -inf;
    n = rd();
    m = rd();
    for(int i = 1; i <= n; ++i) 
    {
        a[i].val = rd();
        a[i].p[0] = i;
        a[i].p[1] = last[a[i].val];
        a[last[a[i].val]].p[2] = i;
        last[a[i].val] = i;
    }
    for(int i = 1; i <= n; ++i) 
        if(!a[i].p[2])
            a[i].p[2] = n + 1;
    root = build(1, n, 0);
    while(m--)
    {
        int l = (rd() + ans) % n + 1, r = (rd() + ans) % n + 1;
        if(l > r) swap(l, r);
        ans = 0;
        query(root, l, r);
        printf("%d\n", ans); 
    }
    return 0;
}
View Code

 

posted @ 2017-11-23 00:32  19992147  阅读(180)  评论(0编辑  收藏  举报