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
  • 相关阅读:
    服务部署 RPC vs RESTful
    模拟浏览器之从 Selenium 到splinter
    windows程序设计 vs2012 新建win32项目
    ubuntu python 安装numpy,scipy.pandas.....
    vmvare 将主机的文件复制到虚拟机系统中 安装WMware tools
    ubuntu 修改root密码
    python 定义类 简单使用
    python 定义函数 两个文件调用函数
    python 定义函数 调用函数
    python windows 安装gensim
  • 原文地址:https://www.cnblogs.com/starve/p/13844049.html
Copyright © 2011-2022 走看看