zoukankan      html  css  js  c++  java
  • 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
    ", ans); 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    64位平台支持大于2 GB大小的数组
    NET Framework 4.5新特性 数据库的连接加密保护。
    永无止境之网站的伸缩性架构
    ASP.NET MVC IOC 之Ninject攻略
    C# 中几个小“陷阱”
    AngularJS的依赖注入方式
    JVM内存配置详解(转)
    StringBuilder、StringBuffer和String三者的联系和区别(转)
    Java线程的生命周期(转)
    Java程序员须知的七个日志管理工具(转)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7882103.html
Copyright © 2011-2022 走看看