HDU6274 Master of Sequence(二分+预处理)

可以把式子进行拆分,拆分完后,我们关注的是两个整除后的关系以及两个余数之间的关系。

余数只要相减那么答案就是建议,否则答案不变。这是因为两个余数相减,除a[i]是不可能大于1的,但是可以小于0,因为是下取整,所以答案-1.

因此我们可以分三层维护这个答案。

现在的关键是如何快速维护这几个答案。因为a[i]只有1000,这告诉我们余数也不会大于1000,所以我们可以开个二维数组去记录每个a[i]对应的所有b[i]产生的答案

因为询问也不会超过1000,我们发现这个有单调性,可以二分check,复杂度也没问题。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll inf=1e15;
typedef long long ll;
int n,m;
ll sum[2020][2020];
int a[N],b[N];
ll ans=0;
bool check(ll x,ll y){
    ll res=0;
    for(int i=1;i<=1000;i++){
        res+=sum[i][0]*(x/i);
        res-=sum[i][x%i+1];
    }
    return res>=y;
}
ll solve(ll x){
    ll l=1,r=inf;
    while(l<r){
        ll mid=l+r>>1;
        if(check(mid,x)){
            r=mid;
        }
        else{
            l=mid+1;
        }
    }
    return l;
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        int i,j;
        ans=0;
        for(i=1;i<=1000;i++){
            for(j=0;j<=1000;j++)
                sum[i][j]=0;
        }
        for(i=1;i<=n;i++){
            cin>>a[i];
        }
        for(i=1;i<=n;i++){
            cin>>b[i];
        }
        for(i=1;i<=n;i++){
            sum[a[i]][b[i]%a[i]]++;
            ans+=b[i]/a[i];
        }
        for(i=1;i<=1000;i++){
            for(j=i-1;j>=0;j--){
                sum[i][j]+=sum[i][j+1];
            }
        }
        while(m--){
            int opt;
            cin>>opt;
            ll x,y;
            if(opt==1){
                cin>>x>>y;
                ans-=b[x]/a[x];
                ans+=b[x]/y;
                for(i=b[x]%a[x];i>=0;i--){
                    sum[a[x]][i]--;
                }
                for(i=b[x]%y;i>=0;i--){
                    sum[y][i]++;
                }
                a[x]=y;
            }
            else if(opt==2){
                cin>>x>>y;
                ans-=b[x]/a[x];
                ans+=y/a[x];
                for(i=b[x]%a[x];i>=0;i--){
                    sum[a[x]][i]--;
                }
                for(i=y%a[x];i>=0;i--){
                    sum[a[x]][i]++;
                }
                b[x]=y;
            }
            else{
                cin>>x;
                cout<<solve(x+ans)<<endl;
            }
        }
    }
}
View Code

 

posted @ 2020-09-26 09:36  朝暮不思  阅读(156)  评论(0)    收藏  举报