• Codeforces Round #361 (Div. 2) C D


    C 给出一个m 此时有 四个数 分别为x k*x k*k*x k*k*k*x k大于1 x大于等于1 要求求出来一个最小的值n 使其满足 这四个数中的最大值小于n 这四个数可能的组数为m

    可以看出这四个数递增 所以最大值必定是第四个 

    所以我们二分n 需要注意的是longlong可以定义到1e18 初始应当是l小于等于可能的最小值(0) r大于等于可能的最大值(1e18) 如果初始范围就定义错误的话 二分不会出现正确答案

    在这里由于控制l=mid+1或者r=mid-1 这一类的时候 容易丢失mid 造成一些麻烦 所以采用了一种看起来比较暴力的写法 当满足judge==m时直接break出来 然后while控制变小

    因为如果满足过judge 就一定不是-1

    需要注意的是避免i*i*i爆int 提前初始化省时间

    时间复杂度是二分(最大64 )*1e6

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<math.h>
    #include<queue>
    using namespace std;
    long long n,m;
    long long a[1000050];
    void init()
    {
        for(long long i=1;i<=1000000;i++)
        {
            a[i]=i*i*i;
        }
    }
    long long judge(long long z)
    {
        long long res=0;
        for(int i=2;i<=1000000;i++)
        {
            if(z/a[i]==0)
                return res;
            res+=(z/a[i]);
        }
        return res;
    }
    int main()
    {
        while(~scanf("%lld",&m))
        {
            init();
            long long l=0;
            long long r= 1e18+50000000;
            long long mid;
            while(l<=r)
            {
    
                mid=(l+r)>>1;
                long long z=judge(mid);
                if(z>m)
                {
                    r=mid-1;
                }
                else if(z<m)
                {
                    l=mid+1;
                }
                else break;
            }
            if(judge(mid)==m)
            {
                while(true)
                {
                    mid--;
                    if(judge(mid)==m){
                        continue;
                    }
                    else {
                        printf("%lld
    ",mid+1);
                        break;
                    }
                }
            }
    
            else printf("-1
    ");
        }
    }
    

    D 给出两个数组 求出满足条件的l r组数 max第一组a[l-r] = min第二组b[l-r]

    比赛的时候去掉了线段树莫队rmq 因为如果抽象询问的话 最后是n*(n+1)/2次询问 n是2e5 太大

    也想到过二分 因为看起来应该采用nlogn的办法 然而因为二分需要满足稳定的递增 就排除了

    赛后看题解..居然真的是二分+rmq  记得那场cf感觉奇难 AB打完一个小时就过去了 怎么可能想出来二分+数据结构这种神奇的办法

    这个算法里面 rmq的预处理是nlogn的 查询是1的 二分的查询也是常数的 所以总体是nlogn的

    http://blog.csdn.net/Miracle_ma/article/details/51860149 这道题的思想和rmq模板都来自于这个博客

    每次我们枚举i 以i作为左区间枚举右区间 满足max-min=0

    第一次我们得到的是 最左的不满足的 第二次得到的是 最右的满足的 相减就是i做左区间的右区间范围 

    需要注意的是ans可能爆int

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<map>
    #include<queue>
    #include<iostream>
    #include<vector>
    using namespace std;
    int a[200050];
    int b[200050];
    int aa[200050][25];
    int bb[200050][25];
    int n;
    void rmq_inita()
    {
        for(int i=0; i<n; i++) aa[i][0]=a[i];
        for(int j=1; (1<<j)<=n; j++)
        {
            for(int i=0; i+(1<<j)-1<n; i++)
            {
                aa[i][j]=max(aa[i][j-1],aa[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    void rmq_initb()
    {
        for(int i=0; i<n; i++) bb[i][0]=b[i];
        for(int j=1; (1<<j)<=n; j++)
        {
            for(int i=0; i+(1<<j)-1<n; i++)
            {
                bb[i][j]=min(bb[i][j-1],bb[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int rmqa(int L,int R)
    {
        int k=0;
        while((1<<(k+1))<=R-L+1) k++;
        return max(aa[L][k],aa[R-(1<<k)+1][k]);
    }
    
    int rmqb(int L,int R)
    {
        int k=0;
        while((1<<(k+1))<=R-L+1) k++;
        return min(bb[L][k],bb[R-(1<<k)+1][k]);
    }
    int main()
    {
        while(cin>>n)
        {
            for(int i = 0; i<n; i++)cin>>a[i];
            for(int i = 0; i<n; i++)cin>>b[i];
            rmq_inita();
            rmq_initb();
            long long int ans= 0;
            for(int i=0; i<n; i++)
            {
                long long int res=0;
                int l = i;
                int r = n-1;
                while(l<=r)
                {
                    int mid = (l + r)>>1;
                    if(rmqa(i,mid)-rmqb(i,mid)<0)
                    {
                        l = mid + 1;
                    }
                    else  r = mid - 1;
                }
                res= l;
                l = i;
                r = n-1;
                while(l<=r)
                {
                    int mid = (l + r)>>1;
                    if(rmqa(i,mid)-rmqb(i,mid)>0)
                    {
                        r = mid - 1;
                    }
                    else l = mid + 1;
                }
                ans += l-res;
            }
            printf("%lld
    ",ans);
        }
    }
    

      

  • 相关阅读:
    Ajax 导出Excel 方式
    配置文件类型
    Ionic 发布Release 版本
    $cordovaNetwork 使用
    Web Api 跨域问题
    Python学习(五)--字典
    Python学习(四)--字符串
    Python学习(三)--列表和元组
    mac下安装HTMLTestRunner
    mac下selenium+python环境搭建
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/5755082.html
Copyright © 2020-2023  润新知