HDU-6274 Master of Sequence 数学+二分

HDU-6274 Master of Sequence

题意

给出两个长度为(n)的数组(a)(b),设(S(t)=sum_{i=1}^{n} lfloor frac{t-b_i}{a_i} floor)(m)组操作:

  • (1~x~y),将(a[x])改为(y)
  • (2~x~y),将(b[x])改为(y)
  • (3~k),询问 ( ext{min} {t|kle S(t) })

(nle 10^5,mle 10^4,a_i le 1000,b_i,kle 10^9),第三种操作个数不超过(1000)

分析

先把公式拆分一下。

[S(t)=sum_{i=1}^{n} lfloor frac{t-b_i}{a_i} floor \ =sum_{i=1}^{n} lfloor frac{k1cdot a_i+t\%a_i-k2cdot a_i-b_i\%a_i}{a_i} floor \ =sum_{i=1}^{n} k1-k2-[t\%a_i-b_i\%a_i<0] ]

由于(a_ile 1000),我们二分(t)的大小,对每种(a_i)用桶分别计算((t\%a_i-b_i\%a_i<0))的个数。

Code

#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int T,n,m;
int a[N],b[N];
int sz[1010];
int sum[1010][1010];
inline bool ck(ll x,ll k){
    ll ret=0;
    for(int i=1;i<=1000;++i){
        ret+=x/i*sz[i]-sum[i][x%i+1];
    }
    return ret>=k;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        ll res=0;
        scanf("%d%d",&n,&m);
        memset(sz,0,sizeof sz);
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&b[i]);
            res+=b[i]/a[i];
            sum[a[i]][b[i]%a[i]]++;
            sz[a[i]]++;
        }
        for(int i=1;i<=1000;i++){
            for(int j=1000;j>=0;j--) sum[i][j]+=sum[i][j+1];
        }
        for(int i=1,op,x,y;i<=m;i++){
            scanf("%d%d",&op,&x);
            if(op==1){
                scanf("%d",&y);
                res-=b[x]/a[x];
                for(int j=0;j<=b[x]%a[x];j++) sum[a[x]][j]--;
                sz[a[x]]--;
                a[x]=y;
                res+=b[x]/a[x];
                for(int j=0;j<=b[x]%a[x];j++) sum[a[x]][j]++;
                sz[a[x]]++;
            }else if(op==2){
                scanf("%d",&y);
                res-=b[x]/a[x];
                for(int j=0;j<=b[x]%a[x];j++) sum[a[x]][j]--;
                sz[a[x]]--;
                b[x]=y;
                res+=b[x]/a[x];
                for(int j=0;j<=b[x]%a[x];j++) sum[a[x]][j]++;
                sz[a[x]]++;
            }else{
                ll l=0,r=1e13;
                while(l<=r){
                    ll mid=l+r>>1;
                    if(ck(mid,x+res)) r=mid-1;
                    else l=mid+1;
                }
                printf("%lld
",l);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xyq0220/p/13912298.html