zoukankan      html  css  js  c++  java
  • BZOJ2138 : stone

    根据Hall定理,若存在一个区间满足内部需求数$>$内部石子数,则不存在完美匹配。

    由于区间互不包含,所以设:

    $a[i]$表示右端点$leq i$的区间的容量之和。

    $b[i]$表示左端点$leq i$的区间的容量之和。

    $s[i]$表示前$i$个位置的石子数之和。

    则区间$[l,r]$的:

    石子数$=s[r]-s[l-1]$。

    需求数$=a[r]-b[l-1]$。

    即对于任意$0leq i<jleq n$,要满足:

    $min((s[j]-a[j])-(s[i]-b[i]))geq 0$

    $f[i]=s[i]-a[i]$

    $g[i]=s[i]-b[i]$

    考虑$[l,r]$区间需求数为$k$时对匹配的影响:

    $f[r..n]-=k$

    $g[l..n]-=k$

    那么当$k$取$min(f[geq r])-max(g[<l])$时刚好满足所有限制。

    线段树维护即可。

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

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=40010,M=131100,inf=~0U>>1;
    int n,m,i,x,y,z,P,a[N],f[M],g[M],tf[M],tg[M];
    inline void tagf(int x,int y){f[x]+=y;tf[x]+=y;}
    inline void tagg(int x,int y){g[x]+=y;tg[x]+=y;}
    inline void pb(int x){
      if(tf[x])tagf(x<<1,tf[x]),tagf(x<<1|1,tf[x]),tf[x]=0;
      if(tg[x])tagg(x<<1,tg[x]),tagg(x<<1|1,tg[x]),tg[x]=0;
    }
    inline void up(int x){
      f[x]=min(f[x<<1],f[x<<1|1]);
      g[x]=max(g[x<<1],g[x<<1|1]);
    }
    void build(int x,int a,int b){
      if(a==b){f[x]=g[x]=::a[a];return;}
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
      up(x);
    }
    void changef(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){tagf(x,-p);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)changef(x<<1,a,mid,c,d,p);
      if(d>mid)changef(x<<1|1,mid+1,b,c,d,p);
      up(x);
    }
    void changeg(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){tagg(x,-p);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)changeg(x<<1,a,mid,c,d,p);
      if(d>mid)changeg(x<<1|1,mid+1,b,c,d,p);
      up(x);
    }
    int askf(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return f[x];
      pb(x);
      int mid=(a+b)>>1,t=inf;
      if(c<=mid)t=askf(x<<1,a,mid,c,d);
      if(d>mid)t=min(t,askf(x<<1|1,mid+1,b,c,d));
      return t;
    }
    int askg(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return g[x];
      pb(x);
      int mid=(a+b)>>1,t=-inf;
      if(c<=mid)t=askg(x<<1,a,mid,c,d);
      if(d>mid)t=max(t,askg(x<<1|1,mid+1,b,c,d));
      return t;
    }
    int main(){
      scanf("%d%d%d%d%d",&n,&x,&y,&z,&P);
      for(i=1;i<=n;i++)a[i]=(1LL*(i-x)*(i-x)+1LL*(i-y)*(i-y)+1LL*(i-z)*(i-z))%P,a[i]+=a[i-1];
      build(1,0,n);
      scanf("%d%d%d%d%d%d%d",&m,&a[1],&a[2],&x,&y,&z,&P);
      for(i=3;i<=m;i++)a[i]=(1LL*x*a[i-1]+1LL*y*a[i-2]+z)%P;
      for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        printf("%d
    ",z=min(askf(1,0,n,y,n)-askg(1,0,n,0,x-1),a[i]));
        changef(1,0,n,y,n,z);
        changeg(1,0,n,x,n,z);
      }
      return 0;
    }
    

      

  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/clrs97/p/6427093.html
Copyright © 2011-2022 走看看