• 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;
    }
    

      

  • 相关阅读:
    将新的rpm包添加到本地yum源
    linux cp命令直接覆盖不提示按Y/N的方法
    十一月二十一学习报告
    十一月二十学习报告
    十一月十九学习报告
    十一月十八学习报告
    十一月十七学习报告
    十一月十五学习报告
    十一月十四学习报告
    十一月十三学习报告
  • 原文地址:https://www.cnblogs.com/clrs97/p/6427093.html
Copyright © 2020-2023  润新知