洛谷P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Feynman1999/article/details/83993262

洛谷 P4169 [Violet]天使玩偶/SJY摆棋子

https://www.luogu.org/problemnew/show/P4169

对于曼哈顿距离 考虑四个方向分别求解,因此现在考虑一个方向如何求解

cdq分治时,左边的修改会对右边的询问产生影响,于是使用树状数组维护。那么具体什么样的左边的点会对右边造成影响呢?当然是两个坐标都小于等于询问辣,那么我们对左边点进行排序(不用sort,自然归并即可),对于询问直接访问树状数组就行啦。

img

img

具体维护的是X+Y的最大值

时间复杂度 O ( n l o g 2 n ) O(nlog^2n)

这题时间卡的比较紧 区间最值用线段树会卡掉 所以用树状数组维护

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

int n,m;
const int maxn=3e5+10;
const int maxq=maxn<<1;
const int maxm=2e6+10;
const int inf= 0x3f3f3f3f;
int maxid;

int maxx[maxm<<2];
void Pushup(int rt){
    maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}

void cmax(int &x,int y){
    x= x>y? x : y;
}
//
//void build(int l,int r,int rt){
//    if(l==r){
//        maxx[rt]=-inf;
//        return ;
//    }
//    int m=(l+r)>>1;
//    build(lson);build(rson);
//    Pushup(rt);
//}
//
//void update(int p,int cov,int l,int r,int rt){
//    if(l==r){
//        maxx[rt]=cov;
//        return ;
//    }
//    int m=(l+r)>>1;
//    if(p<=m) update(p,cov,lson);
//    else update(p,cov,rson);
//    Pushup(rt);
//}
//
//int query(int L,int R,int l,int r,int rt){
//    if(L<=l && r<=R) return maxx[rt];
//    int m=(l+r)>>1;
//    int ret=-inf;
//    if(L<=m) cmax(ret,query(L,R,lson));
//    if(R>m) cmax(ret,query(L,R,rson));
//    return ret;
//}

int mx[maxm];
int lowbit(int x) { return x&(-x); }
void add(int x,int v){ for(int i=x;i<=maxid;i+=lowbit(i))cmax(mx[i],v);}
int query(int x){ int res=-inf; for(int i=x;i>0;i-=lowbit(i))cmax(res,mx[i]); return res;}
void cls(int x){ for(int i=x;i<=maxid;i+=lowbit(i))mx[i]=-inf;}


struct node{
    int x,y;
    int type;
    int id;
    bool operator < (const node & rhs) const{
        return x == rhs.x ? y<= rhs.y  :  x <= rhs.x ;
    }
}no[maxq];
int ans[maxq];

node tmp[maxq];
node tmp2[maxq];

void cdq(int L,int R)
{
    if(L==R) return ;
    int M=(L+R)>>1;
    cdq(L,M);cdq(M+1,R);
    int l=L,r=M+1;
    int tid=1;
    while(l<=M && r<=R){
        if(no[l]<no[r]){
            if(no[l].type==1){
                //update(no[l].y,no[l].y+no[l].x,1,maxid,1);
                add(no[l].y,no[l].x+no[l].y);
            }
            tmp[tid++]=no[l++];
        }
        else{
            //    cout<<query(1,no[r].y,1,maxid,1)<<endl;
            if(no[r].type==2) {
                //ans[no[r].id]=min(ans[no[r].id],no[r].x+no[r].y-query(1,no[r].y,1,maxid,1));
                ans[no[r].id]=min(ans[no[r].id],no[r].x+no[r].y-query(no[r].y));
            }
            tmp[tid++]=no[r++];
        }
    }
    while(l<=M){
        tmp[tid++]=no[l++];
    }
    while(r<=R){
        if(no[r].type==2){
            //ans[no[r].id]=min(ans[no[r].id],no[r].x+no[r].y-query(1,no[r].y,1,maxid,1));
            ans[no[r].id]=min(ans[no[r].id],no[r].x+no[r].y-query(no[r].y));
        }
        tmp[tid++]=no[r++];
    }
    for(int i=L;i<=M;++i){
        if(no[i].type==1) {
            //update(no[i].y,-inf,1,maxid,1);
            cls(no[i].y);
        }
    }
    for(int i=L;i<=R;++i) no[i]=tmp[i-L+1];
}

int main()
{
 //   freopen("in.txt","r",stdin);
    maxid=0;
    memset(mx,-inf,sizeof(mx));
    int idx=1;
    int aid=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&no[idx].x,&no[idx].y);
        no[idx].x++;
        no[idx].y++;
        maxid=max(maxid,no[idx].x);
        maxid=max(maxid,no[idx].y);
        no[idx++].type=1;
    }
    for(int i=1;i<=m;++i){
        int type;
        scanf("%d",&type);
        if(type==1){
            no[idx].type=1;
            scanf("%d%d",&no[idx].x,&no[idx].y);
            no[idx].x++;
            no[idx].y++;
            maxid=max(maxid,no[idx].x);
            maxid=max(maxid,no[idx].y);
            idx++;
        }
        else{
            no[idx].type=2;
            scanf("%d%d",&no[idx].x,&no[idx].y);
            no[idx].x++;
            no[idx].y++;
            maxid=max(maxid,no[idx].x);
            maxid=max(maxid,no[idx].y);
            no[idx].id=aid;
            aid++;
            idx++;
        }
    }
    for(int i=1;i<idx;++i) tmp2[i]=no[i];
    for(int i=1;i<aid;++i) ans[i]=inf;
    maxid+=1;
    //build(1,maxid,1);
    cdq(1,idx-1);
    for(int i=1;i<idx;++i) tmp2[i].x=maxid-tmp2[i].x,no[i]=tmp2[i];
    cdq(1,idx-1);
    for(int i=1;i<idx;++i) tmp2[i].y=maxid-tmp2[i].y,no[i]=tmp2[i];
    cdq(1,idx-1);
    for(int i=1;i<idx;++i) tmp2[i].x=maxid-tmp2[i].x,no[i]=tmp2[i];
    cdq(1,idx-1);
    for(int i=1;i<aid;++i){
         printf("%d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Feynman1999/article/details/83993262