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 }