zoukankan      html  css  js  c++  java
  • BZOJ2567 : 篱笆

    设第$i$个区间的左端点为$a[i]$,区间长度为$len$,要覆盖的部分的长度为$all$,因为区间左端点递增,所以最优方案中它们的位置仍然递增。

    对于链的情况,要满足三个条件:

    1. 区间$i$可以接上区间$i-1$

    设$f[i]$表示最优解中第$i$个区间左端点的位置,则$f[i]=min(f[i-1]+len,a[i]+ans)$且$f[i]geq a[i]-ans$。

    所以$ansgeqmax(a[i]-f[i])=max(a[i]-a[j]-ans-(i-j) imes len)$,

    即$ansgeqfrac{max(a[i]-a[j]-(i-j) imes len)}{2}(lleq jleq ileq r)$。

    2. 可以覆盖位置$0$

    即$f[l]leq 0$,所以$a[i]+ans-(i-l) imes lenleq 0$,

    故$ansgeqmax(a[i]-(i-l) imes len)$。

    3. 可以覆盖位置$all$

    即$f[r]geq all-len$,所以$a[i]+ans+(r-i) imes lengeq all-len$,

    故$ansgeqmax(all-len-a[i]-(r-i) imes len)$。

    对于环的情况,只需要把区间复制一份,那么只需要满足条件1就能保证没有死角:

    即$ansgeqfrac{max(a[i]-a[j]-(i-j) imes len)}{2}(lleq jleq ileq r)$,

    且$ansgeqfrac{max(a[i]+all-a[j]-(r-l+1-(j-i)) imes len)}{2}(lleq i<jleq r)$。

    以上所有信息都可以通过线段树进行区间合并,时间复杂度$O(mlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=120010,M=262150,BUF=30000000;
    const ll inf=1LL<<60;
    int T,n,m,type,i,x,y;ll all,r,len,a[N],b[N],ans;bool flag;char Buf[BUF],*buf=Buf;
    struct P{
      ll v,w,ma,mi;
      void set(ll b){v=w=0,ma=mi=b;}
      P operator+(const P&b){
        P c;
        c.v=max(max(v,b.v),b.ma-mi);
        c.w=max(max(w,b.w),ma-b.mi);
        c.ma=max(ma,b.ma);
        c.mi=min(mi,b.mi);
        return c;
      }
    }v[M],val;
    inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
    inline void read(ll&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
    void build(int x,int a,int b){
      if(a==b){v[x].set(::b[a]);return;}
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
      v[x]=v[x<<1]+v[x<<1|1];
    }
    void ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){
        if(!flag)val=v[x];else val=val+v[x];
        flag=1;
        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 x,int y){
      flag=0;
      ask(1,1,n,x,y);
      if(type==1){
        ans=val.v;
        ans=max(ans,(val.ma+len*x)*2);
        ans=max(ans,(all-len-val.mi-len*y)*2);
      }else ans=max(val.v,val.w-len*(y-x+1)+all);
      printf("%lld.%lld0000
    ",ans/2,ans%2*5);
    }
    int main(){
      fread(Buf,1,BUF,stdin);read(T);
      while(T--){
        read(n),read(all),read(r),read(m),read(type);
        len=r*2;
        for(i=1;i<=n;i++)read(a[i]),a[i]-=r,b[i]=a[i]-len*i;
        build(1,1,n);
        query(1,n);
        while(m--)read(x),read(y),query(x,y);
      }
      return 0;
    }
    

      

  • 相关阅读:
    函数与方法(方法前 +
    1362 : 修补木桶 -- 最长的最短边
    149. Max Points on a Line *HARD* 求点集中在一条直线上的最多点数
    148. Sort List -- 时间复杂度O(n log n)
    133. Clone Graph 138. Copy List with Random Pointer 拷贝图和链表
    debug && release
    静态库 && 动态库
    枚举
    获取当前用户所使用的是什么浏览器
    java实现在图片上编辑文本内容
  • 原文地址:https://www.cnblogs.com/clrs97/p/10363763.html
Copyright © 2011-2022 走看看