zoukankan      html  css  js  c++  java
  • BZOJ1099 : [POI2007]树Drz

    首先1与i交换,n与i交换,i与i+1交换的可以$O(n)$算出。

    然后只需要考虑i与x交换(1<i,x<n且|i-x|>1)。

    a[i]=h[i-1]

    b[i]=h[i+1]

    f[i]=|h[i-1]-h[i]|+|h[i+1]-h[i]|

    c[i]=min(a[i],b[i])

    d[i]=max(a[i],b[i])

    则交换i与x对答案的贡献为

    -f[i]-f[x]

    +|a[i]-h[x]|+|b[i]-h[x]|

    +|h[i]-a[x]|+|h[i]-b[x]|

    对第二行进行分类讨论:

    1.h[x]<=min(a[i],b[i])

    a[i]+b[i]-h[x]*2

    2.min(a[i],b[i])<=h[x]<=max(a[i],b[i])

    |a[i]-b[i]|

    3.h[x]>=max(a[i],b[i])

    h[x]*2-a[i]-b[i]

    对第三行进行分类讨论:

    1.h[i]<=min(a[x],b[x])

    a[x]+b[x]-h[i]*2

    2.min(a[x],b[x])<=h[i]<=max(a[x],b[x])

    |a[x]-b[x]|

    3.h[i]>=max(a[x],b[x])

    h[i]*2-a[x]-b[x]

    所以分9种情况进行讨论,用扫描线+线段树即可完成询问。时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=50010,inf=~0U>>1;
    int n,m,i,now,h[N],a[N],b[N],c[N],d[N],f[N],loc[N],v[131073],ans[N];ll H[N],B[N],sum;
    struct Q{int x,l,r,z,t;Q(){}Q(int _x,int _l,int _r,int _z,int _t){x=_x,l=_l,r=_r,z=_z,t=_t;}}q[N*3];
    inline bool cmp1(Q a,Q b){return a.x==b.x?a.t<b.t:a.x<b.x;}
    inline bool cmp2(Q a,Q b){return a.x==b.x?a.t<b.t:a.x>b.x;}
    inline int getl(ll x){
      x=x*n;
      int l=1,r=n,mid,t;
      while(l<=r)if(B[mid=(l+r)>>1]>=x)r=(t=mid)-1;else l=mid+1;
      return t;
    }
    inline int getr(ll x){
      x=x*n+n-1;
      int l=1,r=n,mid,t;
      while(l<=r)if(B[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline int getx(ll x){
      int l=1,r=n,mid,t;
      while(l<=r)if(B[mid=(l+r)>>1]>=x)r=(t=mid)-1;else l=mid+1;
      return t;
    }
    inline int abs(int x){return x>0?x:-x;}
    inline void up(int&a,int b){if(a>b)a=b;}
    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';}
    void build(int x,int a,int b){
      v[x]=inf;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void change(int x,int a,int b,int c,int p){
      if(a==b){v[x]=p;return;}
      int mid=(a+b)>>1;
      c<=mid?change(x<<1,a,mid,c,p):change(x<<1|1,mid+1,b,c,p);
      v[x]=min(v[x<<1],v[x<<1|1]);
    }
    void ask(int x,int a,int b,int c,int d){
      if(c>d||v[x]>=now)return;
      if(c<=a&&b<=d){up(now,v[x]);return;}
      int mid=(a+b)>>1;
      if(c<=mid)ask(x<<1,a,mid,c,d);
      if(d>mid)ask(x<<1|1,mid+1,b,c,d);
    }
    inline void query(int l,int r,int p){
      int x=loc[p-1],y=loc[p+1];
      if(x>y)swap(x,y);
      if(y<l||x>r){
        ask(1,1,n,l,r);
        return;
      }
      if(l<=x&&y<=r){
        ask(1,1,n,l,x-1);
        ask(1,1,n,x+1,y-1);
        ask(1,1,n,y+1,r);
        return;
      }
      if(l<=x){
        ask(1,1,n,l,x-1);
        ask(1,1,n,x+1,r);
        return;
      }
      ask(1,1,n,l,y-1);
      ask(1,1,n,y+1,r);
    }
    void S11(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,a[i]+b[i]-h[i]*2-f[i],0);
        q[++m]=Q(h[i],getr(c[i]),0,a[i]+b[i]-h[i]*2-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp2),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(1,q[i].l,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S12(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,abs(a[i]-b[i])-h[i]*2-f[i],0);
        q[++m]=Q(d[i],loc[i],0,0,n);
        q[++m]=Q(h[i],getr(c[i]),0,a[i]+b[i]-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else if(q[i].t==n)change(1,1,n,q[i].l,inf);
        else{
          now=inf,query(1,q[i].l,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S13(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(d[i],loc[i],0,-h[i]*2-a[i]-b[i]-f[i],0);
        q[++m]=Q(h[i],getr(c[i]),0,a[i]+b[i]+h[i]*2-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(1,q[i].l,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S21(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,a[i]+b[i]-f[i],0);
        q[++m]=Q(h[i],getl(c[i]),getr(d[i]),abs(a[i]-b[i])-h[i]*2-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp2),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(q[i].l,q[i].r,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S22(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,abs(a[i]-b[i])-f[i],0);
        q[++m]=Q(d[i],loc[i],0,0,n);
        q[++m]=Q(h[i],getl(c[i]),getr(d[i]),abs(a[i]-b[i])-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else if(q[i].t==n)change(1,1,n,q[i].l,inf);
        else{
          now=inf,query(q[i].l,q[i].r,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S23(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(d[i],loc[i],0,-a[i]-b[i]-f[i],0);
        q[++m]=Q(h[i],getl(c[i]),getr(d[i]),abs(a[i]-b[i])+h[i]*2-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(q[i].l,q[i].r,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S31(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,a[i]+b[i]+h[i]*2-f[i],0);
        q[++m]=Q(h[i],getl(d[i]),0,-a[i]-b[i]-h[i]*2-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp2),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(q[i].l,n,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S32(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(c[i],loc[i],0,abs(a[i]-b[i])+h[i]*2-f[i],0);
        q[++m]=Q(d[i],loc[i],0,0,n);
        q[++m]=Q(h[i],getl(d[i]),0,-a[i]-b[i]-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else if(q[i].t==n)change(1,1,n,q[i].l,inf);
        else{
          now=inf,query(q[i].l,n,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    void S33(){
      for(m=0,i=2;i<n;i++){
        q[++m]=Q(d[i],loc[i],0,h[i]*2-a[i]-b[i]-f[i],0);
        q[++m]=Q(h[i],getl(d[i]),0,h[i]*2-a[i]-b[i]-f[i],i);
      }
      for(sort(q+1,q+m+1,cmp1),build(1,1,n),i=1;i<=m;i++){
        if(!q[i].t)change(1,1,n,q[i].l,q[i].z);
        else{
          now=inf,query(q[i].l,n,q[i].t);
          if(now<inf)up(ans[q[i].t],q[i].z+now);
        }
      }
    }
    int main(){
      for(read(n),i=1;i<=n;i++)read(h[i]);
      for(i=1;i<n;i++)sum+=abs(h[i]-h[i+1]);
      if(n>2){
        f[1]=abs(h[1]-h[2]),f[n]=abs(h[n]-h[n-1]);
        for(i=2;i<n;i++){
          a[i]=h[i-1],b[i]=h[i+1];
          c[i]=min(a[i],b[i]),d[i]=max(a[i],b[i]);
          f[i]=abs(h[i]-h[i-1])+abs(h[i]-h[i+1]);
        }
        for(i=3;i<n;i++){
          up(ans[1],abs(h[i]-h[2])+abs(h[1]-h[i-1])+abs(h[1]-h[i+1])-f[1]-f[i]);
          up(ans[i],abs(h[i]-h[2])+abs(h[1]-h[i-1])+abs(h[1]-h[i+1])-f[1]-f[i]);
        }
        for(i=2;i<n-1;i++){
          up(ans[n],abs(h[i]-h[n-1])+abs(h[n]-h[i-1])+abs(h[n]-h[i+1])-f[n]-f[i]);
          up(ans[i],abs(h[i]-h[n-1])+abs(h[n]-h[i-1])+abs(h[n]-h[i+1])-f[n]-f[i]);
        }
        up(ans[1],abs(h[1]-h[n-1])+abs(h[n]-h[2])-f[1]-f[n]);
        up(ans[n],abs(h[1]-h[n-1])+abs(h[n]-h[2])-f[1]-f[n]);
        if(n>2){
          for(i=2;i<n-1;i++){
            up(ans[i],abs(h[i-1]-h[i+1])+abs(h[i]-h[i+1])+abs(h[i+2]-h[i])-f[i]-f[i+1]+abs(h[i]-h[i+1]));
            up(ans[i+1],abs(h[i-1]-h[i+1])+abs(h[i]-h[i+1])+abs(h[i+2]-h[i])-f[i]-f[i+1]+abs(h[i]-h[i+1]));
          }
          up(ans[1],abs(h[1]-h[3])-abs(h[2]-h[3]));
          up(ans[2],abs(h[1]-h[3])-abs(h[2]-h[3]));
          up(ans[n],abs(h[n]-h[n-2])-abs(h[n-1]-h[n-2]));
          up(ans[n-1],abs(h[n]-h[n-2])-abs(h[n-1]-h[n-2]));
        }
        if(n>4){
          for(i=1;i<=n;i++)B[i]=H[i]=(ll)h[i]*n+i-1;
          sort(B+1,B+n+1);
          for(i=1;i<=n;i++)loc[i]=getx(H[i]);
          S11(),S12(),S13(),S21(),S22(),S23(),S31(),S32(),S33();
        }
      }
      for(i=1;i<=n;i++)printf("%lld
    ",sum+ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    寒假第七天
    寒假第六天
    寒假第五天
    寒假第四天
    leetcode 105 从前序与中序遍历序列构造二叉树
    leetcode 268 丢失的数字
    leetcode 141 环形链表
    判断顶点是否在三角形内部
    java 基本数据类型
    leetcode 20 有效的括号
  • 原文地址:https://www.cnblogs.com/clrs97/p/4611323.html
Copyright © 2011-2022 走看看