• BZOJ2716:[Violet 3]天使玩偶——题解


    http://www.lydsy.com/JudgeOnline/problem.php?id=2716

    http://www.lydsy.com/JudgeOnline/upload/201204/T3des(2).gif

    样例输入

    2 3
    1 1
    2 3
    2 1 2
    1 3 3
    2 4 2

    样例输出

    1
    2

    ————————————————————————————————

    整整一个上午的时间,终于DEBUG出来了,原来是因为我数组开小了……

    首先我们很容易想到一个三元组(t,x,y),其中t为操作时间。

    默认最开始给定的一些点的操作为插入,且时间优先级均高于其他的点。

    那么显然就是三维偏序,CDQ可以上了。

    给t排个序,边归并x边树状数组记录y,然后查即可……

    但是我们怎么求dis啊?

    我们有种玄学的方法叫做分情况讨论。

    分成四种情况:

    对于(x,y)(x1,y1)的dis:

    x+y-(x1+y1)      (x>x1,y>y1)

    x-y-(x1-y1)        (x>x1,y<y1)

    -x+y-(y1-x1)      (x<x1,y>y1)

    -x-y-(-x1-y1)      (x<x1,y<y1)

    其中括号内的东西就是我们要用树状数组来维护的东西,显然当括号内的东西最大的时候我们的距离有最小值。

    那么就变成了维护区间最大值的问题了,显然树状数组是能够胜任这项工作的。

    具体的实现方法看我代码吧……不好描述。

    #include<cstdio>
    #include<queue>
    #include<cctype>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int M=500010;
    const int N=1000010;
    const int INF=10*N;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct rem{
        int t;
        int x;
        int y;
        int pos;
    }q[2*M],tmp[2*M];
    int m,n,cnt=0,ans[M],tree[N],maxy=-1;
    bool cmp(rem a,rem b){
        return (a.t<b.t||(a.t==b.t&&a.x<b.x)||(a.t==b.t&&a.x==b.x&&a.y<b.y)||(a.t==b.t&&a.x==b.x&&a.y==b.y&&a.pos<b.pos));
    }
    inline int lowbit(int t){return t&(-t);}
    void add(int x,int y){
        for(int i=x;i<=maxy;i+=lowbit(i))tree[i]=max(tree[i],y);
        return;
    }
    int query(int x){
        int res=-INF;
        for(int i=x;i>0;i-=lowbit(i))res=max(res,tree[i]);
        return res;
    }
    void cdq(int l,int r){
        if(l>=r)return;
        int mid=(l+r)>>1;
        cdq(l,mid);cdq(mid+1,r);
        for(int i=l,j=l,p=mid+1;i<=r;i++){
        if(j<=mid&&(p>r||q[j].x<=q[p].x))tmp[i]=q[j++];
        else tmp[i]=q[p++];
        }
        ///////////
        for(int i=l;i<=r;i++){
        q[i]=tmp[i];
        if(q[i].t<=mid&&!q[i].pos)add(q[i].y,q[i].x+q[i].y);
        if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],q[i].x+q[i].y-query(q[i].y));
        }
        for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&!q[i].pos){
            for(int j=q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF;
        }
        }
        ///////////
        for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&!q[i].pos)add(maxy-q[i].y,q[i].x-q[i].y);
        if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],q[i].x-q[i].y-query(maxy-q[i].y));
        }
        for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&!q[i].pos){
            for(int j=maxy-q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF;
        }
        }
        ///////////
        for(int i=r;i>=l;i--){
        if(q[i].t<=mid&&!q[i].pos)add(q[i].y,q[i].y-q[i].x);
        if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],-q[i].x+q[i].y-query(q[i].y));
        }
        for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&!q[i].pos){
            for(int j=q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF;
        }
        }
        ///////////
        for(int i=r;i>=l;i--){
        if(q[i].t<=mid&&!q[i].pos)add(maxy-q[i].y,-q[i].x-q[i].y);
        if(q[i].t>mid&&q[i].pos)ans[q[i].pos]=min(ans[q[i].pos],-q[i].x-q[i].y-query(maxy-q[i].y));
        }
        for(int i=l;i<=r;i++){
        if(q[i].t<=mid&&!q[i].pos){
            for(int j=maxy-q[i].y;j<=maxy;j+=lowbit(j))tree[j]=-INF;
        }
        }
        ///////////
        return;
    }
    void clear(){
        maxy++;
        for(int i=1;i<=cnt;i++)ans[i]=INF;
        for(int i=1;i<=maxy;i++)tree[i]=-INF;
        return;
    }
    int main(){
        n=read();
        m=read();
        for(int i=1;i<=n;i++){
        q[i].x=read()+1;
        q[i].y=read()+1;
        q[i].t=i;
        maxy=max(maxy,q[i].y);
        }
        for(int i=n+1;i<=m+n;i++){
        int w=read();
        if(w==1){
            q[i].x=read()+1;
            q[i].y=read()+1;
            q[i].t=i;
            maxy=max(maxy,q[i].y);
        }else{
            q[i].x=read()+1;
            q[i].y=read()+1;
            q[i].t=i;
            q[i].pos=++cnt;
            maxy=max(maxy,q[i].y);
        }
        }
        sort(q+1,q+m+n+1,cmp);
        clear();
        cdq(1,m+n);
        for(int i=1;i<=cnt;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    QT设置32bit 64bit编译
    windows应用程序无边框设置
    分组与聚合数据
    快速排序
    【leetcode】two sum --medium
    【leetcode】path sum--easy
    【leetcode】happy number--easy
    SQL函数
    数据库的高级设计
    c++笔试准备(二)数组全排的问题
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8046555.html
Copyright © 2020-2023  润新知