zoukankan      html  css  js  c++  java
  • k-d tree模板练习

    1. [BZOJ]1941: [Sdoi2010]Hide and Seek

    题目大意:给出n个二维平面上的点,一个点的权值是它到其他点的最长距离减最短距离,距离为曼哈顿距离,求最小权值。(n<=500,000)

    思路:k-d tree裸题。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 500000
    #define INF 0x7FFFFFFF
    int rt,D,q[2];
    struct node
    {
        int p[2],mn[2],mx[2],l,r;
        friend bool operator<(const node&a,const node&b){return a.p[D]<b.p[D];}
    }t[MN+5];
    void up(int k)
    {
        for(int l=t[k].l,r=t[k].r,i=0;i<2;++i)
            t[k].mn[i]=t[k].mx[i]=t[k].p[i],
            l?(t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[l].mx[i])):0,
            r?(t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[r].mx[i])):0;
    }
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=l+r>>1;D^=1;
        nth_element(t+l,t+mid,t+r+1);
        t[mid].l=build(l,mid-1);
        t[mid].r=build(mid+1,r);
        return D^=1,up(mid),mid;
    }
    inline int calmx(int k)
    {
        return max(abs(q[0]-t[k].mn[0]),abs(t[k].mx[0]-q[0]))+
               max(abs(q[1]-t[k].mn[1]),abs(t[k].mx[1]-q[1]));
    }
    void qmx(int k)
    {
        D=max(D,abs(t[k].p[0]-q[0])+abs(t[k].p[1]-q[1]));
        int dl=t[k].l?calmx(t[k].l):-INF,dr=t[k].r?calmx(t[k].r):-INF;
        if(dl>dr){if(dl>D)qmx(t[k].l);if(dr>D)qmx(t[k].r);}
             else{if(dr>D)qmx(t[k].r);if(dl>D)qmx(t[k].l);}
    }
    inline int calmn(int k)
    {
        return max(t[k].mn[0]-q[0],0)+max(q[0]-t[k].mx[0],0)+
               max(t[k].mn[1]-q[1],0)+max(q[1]-t[k].mx[1],0);
    }
    void qmn(int k)
    {
        int x=abs(t[k].p[0]-q[0])+abs(t[k].p[1]-q[1]);if(x)D=min(D,x);
        int dl=t[k].l?calmn(t[k].l):INF,dr=t[k].r?calmn(t[k].r):INF;
        if(dl<dr){if(dl<D)qmn(t[k].l);if(dr<D)qmn(t[k].r);}
             else{if(dr<D)qmn(t[k].r);if(dl<D)qmn(t[k].l);}
    }
    int main()
    {
        int n=read(),i,x,ans=INF;
        for(i=1;i<=n;++i)t[i].p[0]=read(),t[i].p[1]=read();
        rt=build(1,n);
        for(i=1;i<=n;++i)
        {
            q[0]=t[i].p[0];q[1]=t[i].p[1];
            D=-INF;qmx(rt);x=D;
            D=INF;qmn(rt);
            ans=min(ans,x-D);
        }
        printf("%d",ans);
    }

    2. [BZOJ]2648: SJY摆棋子

    题目大意:一开始有n个黑棋,m次操作,每次多摆一个黑棋或者摆上一个白棋并询问离这个白棋最近的黑棋的距离,距离为曼哈顿距离。(n,m<=500,000)

    思路:k-d tree裸题,暴力插点可过,也可以分块重构。

    暴力插

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 1000000
    #define INF 0x7FFFFFFF
    int rt,D,q[2];
    struct node
    {
        int p[2],mn[2],mx[2],l,r;
        friend bool operator<(const node&a,const node&b){return a.p[D]<b.p[D];}
    }t[MN+5];
    inline void up(int k)
    {
        for(int l=t[k].l,r=t[k].r,i=0;i<2;++i)
            t[k].mn[i]=t[k].mx[i]=t[k].p[i],
            l?(t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[l].mx[i])):0,
            r?(t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[r].mx[i])):0;
    }
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=l+r>>1;D^=1;
        nth_element(t+l,t+mid,t+r+1);
        t[mid].l=build(l,mid-1);
        t[mid].r=build(mid+1,r);
        return D^=1,up(mid),mid;
    }
    void ins(int&k,int x){k?(D^=1,ins(t[x]<t[k]?t[k].l:t[k].r,x),0):(k=x,0);up(k);}
    inline int cal(int k)
    {
        return k?max(t[k].mn[0]-q[0],0)+max(q[0]-t[k].mx[0],0)+
                 max(t[k].mn[1]-q[1],0)+max(q[1]-t[k].mx[1],0):INF;
    }
    void query(int k)
    {
        D=min(D,abs(t[k].p[0]-q[0])+abs(t[k].p[1]-q[1]));
        int dl=cal(t[k].l),dr=cal(t[k].r);
        if(dl<dr){if(dl<D)query(t[k].l);if(dr<D)query(t[k].r);}
             else{if(dr<D)query(t[k].r);if(dl<D)query(t[k].l);}
    }
    int main()
    {
        int n,m,i;
        n=read();m=read();
        for(i=1;i<=n;++i)t[i].p[0]=read(),t[i].p[1]=read();
        rt=build(1,n);
        while(m--)read()<2?
            (t[++n].p[0]=read(),t[n].p[1]=read(),D=0,ins(rt,n),0):
            (q[0]=read(),q[1]=read(),D=INF,query(rt),printf("%d
    ",D));
    }

     替罪羊重构版,貌似比暴力还慢……

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 1000000
    #define INF 0x7FFFFFFF
    #define alpha 0.75
    int rt,D,q[2],rD,*rb,rq[MN+5],qn;
    struct node
    {
        int p[2],mn[2],mx[2],l,r,s;
        friend bool operator<(const node&a,const node&b){return a.p[D]<b.p[D];}
    }t[MN+5];
    inline void up(int k)
    {
        t[k].s=t[t[k].l].s+t[t[k].r].s+1;
        for(int l=t[k].l,r=t[k].r,i=0;i<2;++i)
            t[k].mn[i]=t[k].mx[i]=t[k].p[i],
            l?(t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[l].mx[i])):0,
            r?(t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[r].mx[i])):0;
    }
    void get(int k)
    {
        if(!k)return;
        rq[++qn]=k;
        get(t[k].l);get(t[k].r);
    }
    bool cmp(int a,int b){return t[a]<t[b];}
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=l+r>>1;D^=1;
        nth_element(rq+l,rq+mid,rq+r+1,cmp);
        t[rq[mid]].l=build(l,mid-1);
        t[rq[mid]].r=build(mid+1,r);
        return D^=1,up(rq[mid]),rq[mid];
    }
    void ins(int&k,int x)
    {
        D^=1;k?(ins(t[x]<t[k]?t[k].l:t[k].r,x),0):(k=x,0);up(k);D^=1;
        if(t[t[x].l].s>t[x].s*alpha||t[t[x].r].s>t[x].s*alpha)rb=&k,rD=D;
    }
    inline int cal(int k)
    {
        return k?max(t[k].mn[0]-q[0],0)+max(q[0]-t[k].mx[0],0)+
                 max(t[k].mn[1]-q[1],0)+max(q[1]-t[k].mx[1],0):INF;
    }
    void query(int k)
    {
        D=min(D,abs(t[k].p[0]-q[0])+abs(t[k].p[1]-q[1]));
        int dl=cal(t[k].l),dr=cal(t[k].r);
        if(dl<dr){if(dl<D)query(t[k].l);if(dr<D)query(t[k].r);}
             else{if(dr<D)query(t[k].r);if(dl<D)query(t[k].l);}
    }
    int main()
    {
        int n,m,i;
        n=read();m=read();
        for(i=1;i<=n;++i)t[i].p[0]=read(),t[i].p[1]=read(),rq[i]=i;
        rt=build(1,n);
        while(m--)read()<2?
            (t[++n].p[0]=read(),t[n].p[1]=read(),D=0,rb=0,ins(rt,n),rb?(qn=0,get(*rb),D=rD,*rb=build(1,qn),0):0):
            (q[0]=read(),q[1]=read(),D=INF,query(rt),printf("%d
    ",D));
    }

    3. [BZOJ]4066: 简单题

    题目大意:一个n*n的矩阵,一开始元素均为0,每次使一个元素加上一个值或者查询一个子矩阵内元素和,强制在线,内存限制20MB。(n<=500,000,操作数<=200,000)

    思路:cdq和线段树都被封死了,用k-d tree分块重构乱暴力,复杂度O(能过)。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 200000
    #define INF 0x7FFFFFFF
    int rt,D,mn[2],mx[2];
    struct node
    {
        int p[2],w,mn[2],mx[2],l,r,s;
        friend bool operator<(const node&a,const node&b){return a.p[D]<b.p[D];}
    }t[MN+5];
    inline void up(int k)
    {
        t[k].s=t[t[k].l].s+t[t[k].r].s+t[k].w;
        for(int l=t[k].l,r=t[k].r,i=0;i<2;++i)
            t[k].mn[i]=t[k].mx[i]=t[k].p[i],
            l?(t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[l].mx[i])):0,
            r?(t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]),t[k].mx[i]=max(t[k].mx[i],t[r].mx[i])):0;
    }
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=l+r>>1;D^=1;
        nth_element(t+l,t+mid,t+r+1);
        t[mid].l=build(l,mid-1);
        t[mid].r=build(mid+1,r);
        return D^=1,up(mid),mid;
    }
    void ins(int&k,int x){D^=1;k?(ins(t[x]<t[k]?t[k].l:t[k].r,x),0):(k=x,0);up(k);}
    inline bool in(int k)
    {
        return mn[0]<=t[k].mn[0]&&t[k].mx[0]<=mx[0]&&
               mn[1]<=t[k].mn[1]&&t[k].mx[1]<=mx[1];
    }
    inline bool pin(int k)
    {
        return mn[0]<=t[k].p[0]&&t[k].p[0]<=mx[0]&&
               mn[1]<=t[k].p[1]&&t[k].p[1]<=mx[1];
    }
    inline bool out(int k)
    {
        return mx[0]<t[k].mn[0]||mn[0]>t[k].mx[0]||
               mx[1]<t[k].mn[1]||mn[1]>t[k].mx[1];
    }
    int query(int k)
    {
        return !k||out(k)?0:in(k)?t[k].s:(pin(k)?t[k].w:0)+query(t[k].l)+query(t[k].r);
    }
    int main()
    {
        int n=0,l=0,p;read();
        while((p=read())<3)
            if(p<2)
            {
                t[++n].p[0]=read()^l;t[n].p[1]=read()^l;t[n].w=read()^l;
                D=0;t[rt].s%10000?(ins(rt,n),0):rt=build(1,n);
            }
            else
            {
                mn[0]=read()^l;mn[1]=read()^l;
                mx[0]=read()^l;mx[1]=read()^l;
                printf("%d
    ",l=query(rt));
            }
    }
  • 相关阅读:
    Java实现 LeetCode 61 旋转链表
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 59 螺旋矩阵 II
    VC 2005 解决方案的目录结构设置和管理
    Visual C++ 设置适合自己的解决方案目录结构
    瑞蓝RL-NDVM-A16网络视频解码器 视频上墙解决方案专家--数字视频解码矩阵
    为什么类的定义中不能包含其自身类型,但是能包含其自身的指针或引用类型
    C++模板使用介绍
  • 原文地址:https://www.cnblogs.com/ditoly/p/20170331P.html
Copyright © 2011-2022 走看看