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} \rfloor\)\(m\)组操作:

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

\(n\le 10^5,m\le 10^4,a_i \le 1000,b_i,k\le 10^9\),第三种操作个数不超过\(1000\)

分析

先把公式拆分一下。

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

由于\(a_i\le 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\n",l);
            }
        }
    }
    return 0;
}
posted @ 2020-11-01 23:12  xyq0220  阅读(84)  评论(0编辑  收藏  举报