• BZOJ2675 : Bomb


    首先通过不断翻转坐标系,假设三个点以横坐标为第一关键字,纵坐标为第二关键字排序后A在B前面,B在C前面。

    那么只需要处理以下两种情况:

    1.B的纵坐标在AC之间,这时三个点的距离和为$2((x_C+y_C)-(x_A+y_A))$。

    可以用线段树处理出每个点作为B时$x_A+y_A$以及$x_C+y_C$的最值,然后更新答案即可。

    2.B的纵坐标不超过A的纵坐标,这时三个点的距离和为$2((x_C+y_C)-x_A-y_B)$。

    还是考虑枚举B,需要维护它左边每个A与右边每个C合并的答案。

    于是用一棵线段树维护A集合,从n到1依次计算。

    假设现在处理的是点B,那么先把B从A中删除,然后查询答案,再将B加入C集合中,也就是在A集合里进行区间更新。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=262150,inf=1000000000;
    int n,i,ansmx,ansmn=inf,c[N],d[N],e[N],fmx[N],fmn[N];
    struct P{int x,y;}a[N],b[N];
    inline bool cmp(const P&a,const P&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    inline bool cmpb(const P&a,const P&b){return a.x<b.x;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void umax(int&a,int b){if(a<b)a=b;}
    inline void umin(int&a,int b){if(a>b)a=b;}
    inline int findl(int x){
      int l=1,r=n,mid,t;
      while(l<=r)if(b[mid=(l+r)>>1].x>=x)r=(t=mid)-1;else l=mid+1;
      return t;
    }
    inline int findr(int x){
      int l=1,r=n,mid,t;
      while(l<=r)if(b[mid=(l+r)>>1].x<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    namespace Sub1{
    struct Node{int mx,mn;}T[M];
    void build(int x,int a,int b){
      T[x].mx=-inf,T[x].mn=inf;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void ins(int x,int a,int b,int c,int p){
      umax(T[x].mx,p),umin(T[x].mn,p);
      if(a==b)return;
      int mid=(a+b)>>1;
      if(c<=mid)ins(x<<1,a,mid,c,p);else ins(x<<1|1,mid+1,b,c,p);
    }
    int askmx(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return T[x].mx;
      int mid=(a+b)>>1,t=-inf;
      if(c<=mid)t=askmx(x<<1,a,mid,c,d);
      if(d>mid)umax(t,askmx(x<<1|1,mid+1,b,c,d));
      return t;
    }
    int askmn(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return T[x].mn;
      int mid=(a+b)>>1,t=inf;
      if(c<=mid)t=askmn(x<<1,a,mid,c,d);
      if(d>mid)umin(t,askmn(x<<1|1,mid+1,b,c,d));
      return t;
    }
    }
    namespace Sub2{
    struct Node{int mxx,mnx,mxv,mnv,mxt,mnt;}T[M];
    inline void tagmx(int x,int p){
      umax(T[x].mxv,T[x].mxx+p);
      umax(T[x].mxt,p);
    }
    inline void tagmn(int x,int p){
      umin(T[x].mnv,T[x].mnx+p);
      umin(T[x].mnt,p);
    }
    inline void pb(int x){
      tagmx(x<<1,T[x].mxt);
      tagmx(x<<1|1,T[x].mxt);
      tagmn(x<<1,T[x].mnt);
      tagmn(x<<1|1,T[x].mnt);
      T[x].mxt=-inf,T[x].mnt=inf;
    }
    inline void up(int x){
      T[x].mxx=max(T[x<<1].mxx,T[x<<1|1].mxx);
      T[x].mnx=min(T[x<<1].mnx,T[x<<1|1].mnx);
      T[x].mxv=max(T[x<<1].mxv,T[x<<1|1].mxv);
      T[x].mnv=min(T[x<<1].mnv,T[x<<1|1].mnv);
    }
    void build(int x,int a,int b){
      T[x].mxt=-inf,T[x].mnt=inf;
      if(a==b){
        T[x].mxx=T[x].mnx=e[a];
        T[x].mxv=-inf,T[x].mnv=inf;
        return;
      }
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
    }
    void del(int x,int a,int b,int c){
      if(a==b){
        T[x].mxx=T[x].mxv=-inf;
        T[x].mnx=T[x].mnv=inf;
        return;
      }
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)del(x<<1,a,mid,c);else del(x<<1|1,mid+1,b,c);
      up(x);
    }
    void change(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){
        tagmx(x,p);
        tagmn(x,p);
        return;
      }
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d,p);
      if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
      up(x);
    }
    int askmx(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return T[x].mxv;
      pb(x);
      int mid=(a+b)>>1,t=-inf;
      if(c<=mid)t=askmx(x<<1,a,mid,c,d);
      if(d>mid)umax(t,askmx(x<<1|1,mid+1,b,c,d));
      return up(x),t;
    }
    int askmn(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return T[x].mnv;
      pb(x);
      int mid=(a+b)>>1,t=inf;
      if(c<=mid)t=askmn(x<<1,a,mid,c,d);
      if(d>mid)umin(t,askmn(x<<1|1,mid+1,b,c,d));
      return up(x),t;
    }
    }
    void solve(){
      for(sort(a+1,a+n+1,cmp),i=1;i<=n;i++)b[i].x=a[i].y,b[i].y=i;
      for(sort(b+1,b+n+1,cmpb),i=1;i<=n;i++)c[i]=findl(a[i].y),d[b[i].y]=i;
      for(i=1;i<=n;i++)e[d[i]]=-a[i].x;
      for(Sub1::build(1,1,n),i=1;i<=n;i++){
        fmx[i]=Sub1::askmx(1,1,n,1,c[i]);
        fmn[i]=Sub1::askmn(1,1,n,1,c[i]);
        Sub1::ins(1,1,n,c[i],-a[i].x-a[i].y);
      }
      for(Sub1::build(1,1,n),i=n;i;i--){
        umax(ansmx,Sub1::askmx(1,1,n,c[i],n)+fmx[i]);
        umin(ansmn,Sub1::askmn(1,1,n,c[i],n)+fmn[i]);
        Sub1::ins(1,1,n,c[i],a[i].x+a[i].y);
      }
      for(Sub2::build(1,1,n),i=n;i;i--){
        Sub2::del(1,1,n,d[i]);
        umax(ansmx,Sub2::askmx(1,1,n,c[i],n)-a[i].y);
        umin(ansmn,Sub2::askmn(1,1,n,c[i],n)-a[i].y);
        Sub2::change(1,1,n,1,findr(a[i].y),a[i].x+a[i].y);
      }
    }
    int main(){
      for(read(n),i=1;i<=n;i++)read(a[i].x),read(a[i].y);
      solve();
      for(i=1;i<=n;i++)a[i].x*=-1,a[i].y*=-1;
      solve();
      for(i=1;i<=n;i++)a[i].x*=-1;
      solve();
      for(i=1;i<=n;i++)a[i].x*=-1,a[i].y*=-1;
      solve();
      return printf("%d
    %d",ansmx*2,ansmn*2),0;
    }
    

      

  • 相关阅读:
    linux命令之free篇
    linux操作之逻辑分区与交换分区篇
    linux之软连接,硬连接篇
    Linux之磁盘分区篇
    Linux命令之vi篇
    JVM总结-垃圾回收算法
    JVM总结-字节码
    JVM总结-java对象的内存布局
    JVM-synchronized怎么实现的?
    JVM总结-invokedynamic
  • 原文地址:https://www.cnblogs.com/clrs97/p/4872267.html
Copyright © 2020-2023  润新知