zoukankan      html  css  js  c++  java
  • BZOJ 2716: [Violet 3]天使玩偶 | CDQ分治

    题目:

    南开OJ有非权限提交处

    http://oi.nks.edu.cn/zh/Problem/Details/2739


    题解:

    鹅鹅鹅....有三维(t,x,y),所以可以用CDQ解决的好题

    初始点就是t超级小的点

    先按x排个序,时间作为分治的第二维,这样只有前半段时间的修改操作对后半段时间的询问操作需要在当前solve处理,y作为需要用数据结构维护的第三维

    考虑把曼哈顿距离展开变成没有绝对值的式子,但是四种情况不好维护.

    如果以某一次询问的点(x0,y0)为源点,显然答案一定在四个象限中的一个

    考虑只维护第三象限的答案,那么绝对值式子可以变成(x0+y0)-(x+y)

    用树状数组可以维护y0位置之前的前缀最大值

    这样每次修改操作就在y位置插入(x+y)就可以做到维护位于第三象限的答案

    其他象限的答案我们只要旋转坐标轴变成第三象限即可

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 1000010
    #define INF 0x7fffffff
    using namespace std;
    int n,m;
    struct node
    {
        int id,op,x,y,pos;
        bool operator < (const node &b) const
        {
            if (x!=b.x) return x<b.x;
            if (y!=b.y) return y<b.y;
            return op<b.op;
        }
    }q[N],tmp[N];
    int ans[N],tot,t[2*N],lim=N;
    void insert(int x,int w)
    {
        for (;x<=lim;x+=x&-x) t[x]=max(t[x],w);
    }
    int query(int x)
    {
        int ret=0;
        for (;x;x-=x&-x)
        ret=max(ret,t[x]);
        return ret;
    }
    void clear(int x)
    {
        for (;x<=lim;x+=x&-x) t[x]=0;
    }
    void solve(int l,int r)
    {
        if (l==r) return ;
        int mid=l+r>>1;
        for (int i=l;i<=r;i++)
        {
        if (q[i].id<=mid && q[i].op==1)
            insert(q[i].y,q[i].y+q[i].x);
        if (q[i].id>mid && q[i].op==2)
        {
            int t=query(q[i].y);
            if (t!=0)
            ans[q[i].pos]=min(ans[q[i].pos],q[i].x+q[i].y-t);
        }
        }
        for (int k=l,i=l,j=mid+1;k<=r;k++)
        {
        if (q[k].id<=mid && q[k].op==1)
            clear(q[k].y);
        if (q[k].id<=mid) tmp[i++]=q[k];
        else tmp[j++]=q[k];
        }
        for (int i=l;i<=r;i++)
        q[i]=tmp[i];
        solve(l,mid);
        solve(mid+1,r);
        
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1,x,y;i<=n;i++)
        {
        scanf("%d%d",&x,&y);
        q[i]=(node){i,1,x+1,y+1,0};
        }
        for (int i=1,op,x,y;i<=m;i++)
        {
        scanf("%d%d%d",&op,&x,&y);
        if (op==1) q[i+n]=(node){i+n,1,x+1,y+1,0};
        else q[i+n]=(node){i+n,2,x+1,y+1,++tot},ans[tot]=INF;
        }
        sort(q+1,q+1+n+m); solve(1,n+m);
        for (int i=1;i<=n+m;i++) q[i].y=lim-q[i].y;
        sort(q+1,q+1+n+m);solve(1,n+m);
        for (int i=1;i<=n+m;i++) q[i].x=lim-q[i].x;
        sort(q+1,q+1+n+m);solve(1,n+m);
        for (int i=1;i<=n+m;i++) q[i].y=lim-q[i].y;
        sort(q+1,q+1+n+m);solve(1,n+m);
        for (int i=1;i<=tot;i++)
        printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Linux 多线程编程 实例 1
    面试题-链表反转c实现
    information_schema.TABLES
    mongodb遇到的错误
    MySQL优化的奇技淫巧之STRAIGHT_JOIN
    mongodb安装
    XtraBackup安装
    提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)
    我用 TypeScript 语言的七个月
    Grunt之添加文件监视:Grunt-watch (已备份)
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8109361.html
Copyright © 2011-2022 走看看