bzoj2716 [ Violet 3 ] --cdq分治+树状数组

树状数组打错调了一个小时。。。

对于点(x,y),其它点只会在他的左下、右下、左上、右上四个方向上。我们只需求在左下方向上就可以了,因为其他方向可以通过改变相对位置求得。

考虑cdq分治。先按x坐标排序,然后将区间[l,r]分为[l,mid],[mid+1,r],因为只求左下方向上的点,所以可以去掉绝对值:dis=x+y-(x'+y')

只需求x'+y'最大的点就可以了。求(X,Y)时将[l,mid]中x值小于X的点的x+y值在树状数组中更新,然后查询y小于Y的最大的x+y,更新答案。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define N 500010
 7 #define lowbit(x) x&-x
 8 struct Node{
 9     int f,x,y,F,b;
10 }a[N<<1],b[N<<1];
11 int i,j,k,x,y,n,m,c[1000010],M1,Ans[N],Num,F,M2;
12 inline int _Max(int x,int y){return x>y?x:y;}
13 inline int _Min(int x,int y){return x>y?y:x;}
14 inline void Update(int x,int y){for(;x<=M1;x+=lowbit(x))c[x]=_Max(c[x],y);}
15 inline int Query(int x){int Ans=0;for(;x;x-=lowbit(x))Ans=_Max(Ans,c[x]);return Ans;}
16 inline void Clear(int x){for(;x<=M1;x+=lowbit(x))c[x]=0;}
17 inline bool Cmp(Node a,Node b){return a.x<b.x||(a.x==b.x&&a.f<b.f);}
18 inline void Solve(int l,int r){
19     if(l==r)return;
20     int Mid=l+r>>1,p1=l;
21     int p2=Mid+1;
22     for(int i=l;i<=r;i++)if(a[i].f<=Mid)b[p1++]=a[i];else b[p2++]=a[i];
23     for(int i=l;i<=r;i++)a[i]=b[i];
24     Solve(l,Mid);
25     int j=l;
26     for(int i=Mid+1;i<=r;i++)
27     if(a[i].b==2){
28         while(j<=Mid&&a[j].x<=a[i].x){
29             if(a[j].b==1)Update(a[j].y,a[j].x+a[j].y);
30             j++;
31         }
32         int q=Query(a[i].y);
33         if(q)Ans[a[i].F]=_Min(Ans[a[i].F],a[i].x+a[i].y-q);
34     }
35     for(int i=l;i<j;i++)if(a[i].b==1)Clear(a[i].y);
36     Solve(Mid+1,r);
37     p1=l;p2=Mid+1;
38     for(int i=l;i<=r;i++)
39     if(p1>Mid)b[i]=a[p2++];else
40     if(p2>r)b[i]=a[p1++];else
41     if(a[p1].x<a[p2].x||(a[p1].x==a[p2].x&&a[p1].f<a[p2].f))b[i]=a[p1++];else b[i]=a[p2++];
42     for(int i=l;i<=r;i++)a[i]=b[i];
43 }
44 int main()
45 {
46     scanf("%d%d",&n,&m);
47     for(i=1;i<=n;i++){
48         scanf("%d%d",&a[i].x,&a[i].y);
49         a[i].x++;a[i].y++;a[i].f=i;a[i].b=1;
50         M2=_Max(M2,a[i].x);
51         M1=_Max(M1,a[i].y);
52     }
53     for(i=n+1;i<=n+m;i++){
54         scanf("%d%d%d",&a[i].b,&a[i].x,&a[i].y);
55         a[i].x++;a[i].y++;a[i].f=i;
56         M2=_Max(M2,a[i].x);
57         M1=_Max(M1,a[i].y);
58         if(a[i].b==2)a[i].F=++Num;
59     }
60     M1++;
61     memset(Ans,0x7f,sizeof(Ans));
62     n+=m;
63     sort(a+1,a+n+1,Cmp);Solve(1,n);
64     for(i=1;i<=n;i++)a[i].x=M2-a[i].x;
65     sort(a+1,a+n+1,Cmp);Solve(1,n);
66     for(i=1;i<=n;i++)a[i].y=M1-a[i].y;
67     sort(a+1,a+n+1,Cmp);Solve(1,n);
68     for(i=1;i<=n;i++)a[i].x=M2-a[i].x;
69     sort(a+1,a+n+1,Cmp);Solve(1,n);
70     for(i=1;i<=Num;i++)printf("%d\n",Ans[i]);
71     return 0;
72 }
bzoj2716

 

posted @ 2017-02-24 10:24  gjghfd  阅读(167)  评论(0编辑  收藏  举报