zoukankan      html  css  js  c++  java
  • hdu6274(向下取整式子分解,二分判断)

    题:http://acm.hdu.edu.cn/showproblem.php?pid=6274

    题意:给定n(n<=1e5)的a[i]和b[i](a[i]<=1e3,b[i]<=1e9) 有m个操作操作一[x,y]:a[x]=y; 操作二[x,y]:b[x]=y;操作三[k]:输出最小的 x 使得S(x)>=k( S(x) =Σ(x-b[i])/a[i] )

    分析:要求最小的,我们考虑对每个询问二分,因为题目保证操作三不会超过1e3次且x越大S(x)越能满足,满足单调性;

       关键在于S(x)的拆分,如果x,b[i]都整除a[i]的话,我们就可以拆分成x/a[i] 和b[i]/a[i] ,但是结果肯定不可能都是这样的;

       那么我们就先把这部分答案存进来,再来考虑不整除的情况,那就考虑取模x%a[i]和b[i]%a[i];

       这里假设x>b[i],若前者小于后者则相当于(x-b[i])/a[i]在直接算(x/a[i]-b[i]/a[i])少了1的贡献的(可以理解为在moda[i]意义下,他们之间间隔没有一个a[i]的长度)

       所以我们直接算sum(b[i]/a[i]),在二分x去算(x/a[i])和可能少了1的部分贡献(用树状数组去维护有多少个是大于(x%a[i])的);

       这里check里面,我们只要枚举余数即可,也就是说1e3次询问三复杂度为1e3*1e3*log1e9  ,10s时限没问题

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int M=1e5+5;
    const int N=1e3+3;
    int a[M],b[M],num[M];
    int n,m;
    struct BIT{
        int tr[N+3];
        void add(int i,int v){
            i++;
            for(;i<N;i+=i&-i) tr[i]+=v;
        }
        int sum(int x){
            int res=0;
            x++;
            for(int i=x;i;i-=i&-i) res+=tr[i];
            return res;
        }
    }bit[N];
    
    bool check(ll x,ll limit){
        ll res=0;
        ///枚举余数
        for(int i=1;i<=1000;i++){
            res+=(x/i)*num[i]-(num[i]-bit[i].sum(x%i));
            if (res>=limit) return 1;
        }
        return res>=limit;
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            ll sum=0;
            memset(num,0,sizeof(num));
            memset(bit,0,sizeof(bit));
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++){
                scanf("%d",&b[i]);
                sum+=b[i]/a[i];
                bit[a[i]].add(b[i]%a[i],1);
                num[a[i]]++;
            }
    
            while(m--){
                int op,x,y;
                scanf("%d",&op);
                if(op==1){
                    scanf("%d%d",&x,&y);
                    sum+=b[x]/y-b[x]/a[x];
                    bit[a[x]].add(b[x]%a[x],-1);
                    bit[y].add(b[x]%y,1);
                    num[a[x]]--,num[y]++;
                    a[x]=y;
                }
                else if(op==2){
                    scanf("%d%d",&x,&y);
                    sum+=y/a[x]-b[x]/a[x];
                    bit[a[x]].add(b[x]%a[x],-1);
                    bit[a[x]].add(y%a[x],1);
                    b[x]=y;
                }
                else{
                    ll k;
                    scanf("%lld",&k);
                    ll l=0,r=2e12,ans;
                    ll limit=k+sum;
                    while(l<=r){
                        ll midd=(l+r)>>1;
                        if(check(midd,limit)){
                            ans=midd;
                            r=midd-1;
                        }
                        else l=midd+1;
                    }
                    printf("%lld
    ",ans);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MyBatis学习(一)
    ORM框架
    Java 核心技术点之注解
    git 分支 合并
    TensorFlow——零碎语法知识点
    TensorFlow——深入MNIST
    tensorflow——MNIST机器学习入门
    TensorFlow——小练习:feed
    TensorFlow——小练习:counter
    TensorFlow——交互式使用会话:InteractiveSession类
  • 原文地址:https://www.cnblogs.com/starve/p/13844049.html
Copyright © 2011-2022 走看看