zoukankan      html  css  js  c++  java
  • BZOJ2670 : Almost

    求出前缀和$s[]$,那么区间$[l,r]$的几乎平均数$=frac{s[r]-s[l-1]}{r-l}$。

    若只有一个询问,那么可以维护$(i,s[i-1])$的凸壳,在凸壳上二分点$(i,s[i])$的切线。

    对于多个询问,考虑分块,那么只需要暴力处理零碎部分即可。

    时间复杂度$O(nsqrt{m}log n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=30010,K=500,inf=2000010;
    typedef long long ll;
    int n,m,i,x,f[N],L,R;ll s[N],a[N],b[N];
    struct E{int l,r,p;}e[M];
    inline bool cmp(const E&a,const E&b){return f[a.l]==f[b.l]?a.r<b.r:f[a.l]<f[b.l];}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    struct P{
      ll u,d;
      P(){}
      P(ll _u,ll _d){u=_u,d=_d;}
      bool operator<(const P&b){return u*b.d<d*b.u;}
      void reset(){u=-inf,d=1;}
      void write(){
        if(!u)puts("0/1");
        else{
          ll t=gcd(u>0?u:-u,d);
          printf("%lld/%lld
    ",u/t,d/t);
        }
      }
    }ans[M],best,tmp,now;
    struct HullA{
      int q[N],t;
      void init(){t=0;}
      void add(int x){
        while(t>1&&(a[q[t]]-a[q[t-1]])*(x-q[t])>=(a[x]-a[q[t]])*(q[t]-q[t-1]))t--;
        q[++t]=x;
      }
      void ask(int x,P&ans){
        if(!t)return;
        int l=2,r=t,o=1,mid;
        while(l<=r){
          mid=(l+r)>>1;
          if((a[q[mid]]-a[q[mid-1]])*(x-q[mid])<=(b[x]-a[q[mid]])*(q[mid]-q[mid-1]))l=(o=mid)+1;else r=mid-1;
        }
        now=P(b[x]-a[q[o]],x-q[o]);
        if(ans<now)ans=now;
      }
    }hA,tA;
    struct HullB{
      int q[N],t;
      void init(){t=0;}
      void add(int x){
        while(t>1&&(b[q[t]]-b[q[t-1]])*(x-q[t])<=(b[x]-b[q[t]])*(q[t]-q[t-1]))t--;
        q[++t]=x;
      }
      void ask(int x,P&ans){
        if(!t)return;
        int l=1,r=t-1,o=t,mid;
        while(l<=r){
          mid=(l+r)>>1;
          if((b[q[mid+1]]-b[q[mid]])*(q[mid]-x)<=(b[q[mid]]-a[x])*(q[mid+1]-q[mid]))r=(o=mid)-1;else l=mid+1;
        }
        now=P(b[q[o]]-a[x],q[o]-x);
        if(ans<now)ans=now;
      }
    }hB;
    inline void read(int&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
      if(f)a=-a;
    }
    inline void vio(int l,int r){
      tA.init();
      tmp.reset();
      while(l<=r)tA.ask(l,tmp),tA.add(l++);
    }
    inline void ask(int l,int r){
      while(l<=r)hB.ask(l++,tmp);
    }
    int main(){
      read(n),read(m);
      for(i=1;i<=n;i++)read(x),s[i]=s[i-1]+x;
      for(i=1;i<=n;i++)a[i]=s[i-1],b[i]=s[i];
      for(i=1;i<=n;i++)f[i]=min(((i-1)/K+1)*K,n);
      for(i=1;i<=m;i++){
        read(e[i].l),read(e[i].r),e[i].p=i;
        if(e[i].l+K+5>=e[i].r){
          vio(e[i].l,e[i].r);
          ans[i]=tmp;
          e[i].l=0;
        }
      }
      sort(e+1,e+m+1,cmp);
      for(i=1;i<=m;i++)if(e[i].l){
        if(f[e[i].l]!=L){
          L=f[e[i].l];
          R=L-1;
          hA.init();
          hB.init();
          best.reset();
        }
        while(R<e[i].r)hB.add(++R),hA.ask(R,best),hA.add(R);
        vio(e[i].l,L-1);
        ask(e[i].l,L-1);
        ans[e[i].p]=best<tmp?tmp:best;
      }
      for(i=1;i<=m;i++)ans[i].write();
      return 0;
    }
    

      

  • 相关阅读:
    synergy一个鼠标键盘控制多台电脑
    matlab 画图参考小程序
    基于centos7的真实机环境下安装 vmware workstastion
    mapreduce运行原理及YARN
    mybatis_resultMap(2)
    (第6天)mybatis_resultMap(1)
    mybatis动态SQL--传入参数为集合,数组类型
    mybatis动态SQL--Trim --Where
    mybatis动态SQL--if--choose
    (第5天)mybatis接口方法入参类型
  • 原文地址:https://www.cnblogs.com/clrs97/p/6498589.html
Copyright © 2011-2022 走看看