• 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
    ",Ans[i]);
    71     return 0;
    72 }
    bzoj2716
  • 相关阅读:
    【XFeng安卓开发笔记】Android开发中如何调用打电话功能
    【XFeng安卓开发笔记】edittext中怎样禁止系统自带键盘弹出但光标还在
    【XFeng安卓开发笔记】android 如何在对话框中获取edittext中的数据
    【nRF51822蓝牙开发笔记】点亮LED灯
    基于R7F0C80212ESP的蓝牙婴儿早教机
    read、write和lseek
    open(/dev/ietctl, O_RDWR) 函数
    通过linux命令来控制板上GP_LED灯亮灭
    更新开发板固件
    PHP_EOL
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6437402.html
Copyright © 2020-2023  润新知