BZOJ 2716 angel doll CDQ partition

Meaning of the questions:

Input:

Output:

Sample longer omitted here

Ideas:

Algorithm: CDQ Partition + Fenwick tree

First, the absolute value of present title,It is certainly easier to remove, The first case is considered classified discussion, inquiry soon as the origin point, and then divided into four quadrants demolition absolute value, but this time will find that in fact not much different from each quadrant of the algorithm, so another idea is that every are all times to the third quadrant, i.e., the conversion by addition and subtraction, for the case of need, \ (a \) position of the point, the doll \ (B \) distance to have direct become \ (DIS = A_x + A_y- (B_x + B_y ) \) Since \ (A_x + a_y \) value is fixed, minimum dis need, so we have to find \ (B_y + B_x \) maximum points.

Because we directly set in the third quadrant, so finding \ (B \) point there is a limit \ (B_y <= A_y \) and \ (B_x <A_x \) plus a time limit, that is, a partial ordering problem. The following ideas: first in chronological order, the pair \ (x \) be divide and conquer, maintain the value of y in a tree array.

Because this data is very slow problem, here are a few optimization :
1, for the time sort, every sort of complexity is \ (O (nlogn) \) to a total of four times, then the complexity is directly blown up, but the actual we can arrange the note at the beginning, every change to transform the direct use of the beginning of the arrangement.

for(int i=1; i<=tot; i++)ans[i]=INF,P[i]=a[i];//这里的P数组就是用来记录初始序列
CDQ(1,tot);
for(int i=1; i<=tot; i++)P[i].x=Mx-P[i].x,a[i]=P[i];

2, in the CDQ \ (X \) ordering can be considered merged with

3, to the beginning of the \ ([1, n] \ ) number only added, it can be directly sorted to return

if(r<=n){
    sort(a+l,a+r+1);
    return;
}

At the same time there is a topic in detail: \ (the X-, the y-\) may be equal to 0, so you can consider are a plus, prevent Fenwick tree into an infinite loop.

With code + Notes:

#include<bits/stdc++.h>
#define M 500005
#define INF 1000000000
#define N 1000005
#define lowbit(x) (x&-x)
using namespace std;
int n,m,ans[M<<1],Mx;
void Rd(int &res) {
    res=0;
    char c;
    while(c=getchar(),c<48);
    do res=(res<<1)+(res<<3)+(c-'0');
    while(c=getchar(),c>=48);
}
struct node {
    int op,x,y,id;
    bool operator<(const node&_)const {
        if(x!=_.x)return x<_.x;
        return y<=_.y;
    }
} a[M<<1],p[M<<1],P[M<<1];
struct Tree {
    int mx[N];
    void Init() {
        memset(mx,0,sizeof(mx));
    }
    void add(int x,int y) {
        while(x<=Mx)mx[x]=max(mx[x],y),x+=lowbit(x);
    }
    int find(int x) {
        int res=0;
        while(x)res=max(res,mx[x]),x-=lowbit(x);
        return res;
    }
    void clear(int x) {
        while(x<=Mx)mx[x]=0,x+=lowbit(x);
    }
} T;
void CDQ(int l,int r) {
    if(r<=n){
        sort(a+l,a+r+1);
        return;
    }
    if(l>=r)return;
    int mid=(l+r)>>1;
    int L=l,R=mid+1;
    int now=l;
    CDQ(l,mid),CDQ(mid+1,r);//正常的归并排序过程中加入计算
    while(L<=mid&&R<=r) {
        if(a[L]<a[R]) {
            if(a[L].op==1)T.add(a[L].y,a[L].x+a[L].y);
            p[now++]=a[L++];
        } else {
            if(a[R].op==2) {
                int t=T.find(a[R].y);
                if(t)ans[a[R].id]=min(ans[a[R].id],a[R].x+a[R].y-t);//t>0表示存在这样的点 因为开始已经将x,y都加了1
            }
            p[now++]=a[R++];
        }
    }
    while(R<=r) {
        if(a[R].op==2) {
            int t=T.find(a[R].y);
            if(t)ans[a[R].id]=min(ans[a[R].id],a[R].x+a[R].y-t);
        }
        p[now++]=a[R++];
    }
    for(int i=l; i<L; i++)if(a[i].op==1)T.clear(a[i].y);//撤销
    while(L<=mid)p[now++]=a[L++];
    for(int i=l; i<=r; i++)a[i]=p[i];
}
int main() {
//  freopen("data.in","r",stdin);
//  freopen("data.out","w",stdout);
    Rd(n),Rd(m);
    for(int i=1; i<=n; i++)Rd(a[i].x),Rd(a[i].y),a[i].op=1,a[i].x++,a[i].y++,Mx=max(Mx,max(a[i].x,a[i].y)),a[i].id=i;
    for(int i=n+1; i<=m+n; i++)Rd(a[i].op),Rd(a[i].x),Rd(a[i].y),a[i].x++,a[i].y++,Mx=max(Mx,max(a[i].x,a[i].y)),a[i].id=i;
    int tot=n+m;Mx++;
    T.Init();
    for(int i=1; i<=tot; i++)ans[i]=INF,P[i]=a[i];//下面是对四个方向的计算
    CDQ(1,tot);
    for(int i=1; i<=tot; i++)P[i].x=Mx-P[i].x,a[i]=P[i];
    CDQ(1,tot);
    for(int i=1; i<=tot; i++)P[i].y=Mx-P[i].y,a[i]=P[i];
    CDQ(1,tot);
    for(int i=1; i<=tot; i++)P[i].x=Mx-P[i].x,a[i]=P[i];
    CDQ(1,tot);
    for(int i=1; i<=tot; i++)if(ans[i]!=INF)printf("%d\n",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/cly1231/p/10983225.html