• BZOJ2716天使玩偶


    不会KD-tree怎么办?CQD硬搞。

    建立正常的平面直角坐标系,首先我们只考虑在目标点左下角的点对目标点的贡献,由于左下点的横纵坐标都小于目标点,那么曼哈顿距离就可以化简了,绝对值去掉后,得到$x2+y2-(x1+y1)$,那么我们的目标就转化为了求横纵坐标以及时间轴都小于目标查询点的更改点所作出的贡献,这是一个三维偏序问题,我们在树状数组中维护x+y的最大值,进而即可更新答案。

    可是这样做我们只是考虑了左下角点的贡献,肯定是会出错的,但是其余位置的点不容易化简绝对值,或者化简完以后的形式比较难以维护,而且个人认为分类的话码量略大。

    那么我们换一个角度,如何将其余位置的点都变化到目标点的左下角。

    直接翻转坐标系就行了,把所有点的横纵坐标都翻转一下,使之分别落于其他象限。那么再次调用cdq即可,注意防负下标。

    这样打的好处就是比较无脑,而且正确性保障很大,但是常数这种东西还是很神奇的。(本代码不保证Bzoj可A)(其实应该不可A,因为main函数返回值是signed)

    #include<bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    #define int long long 
    using namespace std;
    const int inf=0x7fffffffffffff;
    int read(){
        int sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){
            if(x=='-') f=-1;
            x=getchar();
        }while(x>='0'&&x<='9'){
            sum=sum*10+x-'0';
            x=getchar();
        }return sum*f;
    }
    struct rec{
        int x,y,t,id,ty;
        friend bool operator < (const rec &a,const rec &b){
            if(a.t==b.t){
                if(a.x==b.x) return a.y<b.y;
                else return a.x<b.x;
            }else return a.t<b.t;
        }
    }q[6005000],tmp[6005000];
    int n,m,kind,Max,ans[3005000],tr[10005000],_time=1,mk[10005000];
    void change(int pos,int val){
        if(!pos) return ;
        for(int i=pos;i<=Max;i+=lowbit(i))
            if(mk[i]!=_time){
                mk[i]=_time;
                tr[i]=val;
            }
            else tr[i]=max(tr[i],val);
    }
    int ask(int pos){
        int ans=-inf;
        for(int i=pos;i;i-=lowbit(i))
            if(mk[i]==_time) ans=max(ans,tr[i]);
        return ans;
    }
    void cdq(int l,int r){
        if(l==r) return ;
        int mid=l+r>>1;
        cdq(l,mid);cdq(mid+1,r);
        int i=l,j=mid+1,tot=l;
        while(i<=mid&&j<=r){
            if(q[i].x<=q[j].x){
                tmp[tot]=q[i];
                if(!q[i].ty)
                    change(q[i].y,q[i].x+q[i].y);
                ++tot;++i;
            }else {
                tmp[tot]=q[j];
                if(q[j].ty)
                    ans[q[j].id]=min(ans[q[j].id],q[j].x+q[j].y-ask(q[j].y));
                ++tot;++j;
            }
        }
        while(i<=mid){
            tmp[tot]=q[i];
    //        if(!q[i].ty)
    //            change(q[i].y,q[i].x+q[i].y);
            ++tot;++i;
        }
        while(j<=r){
            tmp[tot]=q[j];
            if(q[j].ty)
                ans[q[j].id]=min(ans[q[j].id],q[j].x+q[j].y-ask(q[j].y));
            ++tot;++j;
        }
    /*    for(int i=1;i<=Max;i++)
            cout<<tr[i]<<" ";cout<<endl;*/
    //    for(int k=l;k<=mid;k++) 
        //    if(!q[i].ty) del(q[k].y);
    /*    for(int i=1;i<=Max;i++)
            cout<<tr[i]<<" ";cout<<endl;*/
        _time++;
    //    if(_time>=10000000000) _time=1;
        for(int k=l;k<=r;k++) q[k]=tmp[k];
    }
    signed 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=0;q[i].ty=0;
            Max=max(Max,max(q[i].x,q[i].y));
        }
        for(int i=1;i<=m;i++){
            kind=read();
            if(kind&1){
                q[i+n].x=read()+1;q[i+n].y=read()+1;
                q[i+n].t=i;q[i].ty=0;
            }else {
                q[i+n].x=read()+1;q[i+n].y=read()+1;
                q[i+n].t=i;q[i+n].ty=1;
                q[i+n].id=++ans[0];
                ans[ans[0]]=inf;
            }
            Max=max(Max,max(q[i+n].x,q[i+n].y));
        }n+=m;
    //    cout<<"Max="<<Max<<endl;
        sort(q+1,q+n+1);
        cdq(1,n);
    /*    for(int i=1;i<=n;i++)
            cout<<q[i].t<<" "<<q[i].x<<" "<<q[i].y<<endl;*/
        for(int i=1;i<=n;i++) q[i].x=-q[i].x+Max+1;
        sort(q+1,q+1+n);
    /*    for(int i=1;i<=n;i++)
            cout<<q[i].t<<" "<<q[i].x<<" "<<q[i].y<<endl;*/
        cdq(1,n);
        for(int i=1;i<=n;i++) q[i].y=-q[i].y+Max+1;
        sort(q+1,q+1+n);
        cdq(1,n);
        for(int i=1;i<=n;i++) q[i].x=-q[i].x+Max+1;
        sort(q+1,q+n+1);
        cdq(1,n);
        for(int i=1;i<=ans[0];i++)
            printf("%lld
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    XmlTextWriter学习笔记(转载)
    linux shell数据重定向(输入重定向与输出重定向)详细分析
    手机信息查看
    学员信息管理系统
    DOM4j 学习笔记
    Spinner 学习笔记
    java 网络编程学习笔记
    Oracle数据库远程连接方式之:不需要安装客户端软件方法!
    SQL 基础语法(创建表空间、用户、并授予权限、数据的增删改查) (学习笔记)
    北大青鸟第一单元项目 (小说管理系统)
  • 原文地址:https://www.cnblogs.com/Yu-shi/p/11252540.html
Copyright © 2020-2023  润新知