• Codeforce 8.15-8.22做题记录


    Chopping Carrots (Easy Version)-1700

    题意:给定长度为n的数组a,数组p长度为n且其中每个元素可在[1,k]间取整数。求 m a x i ⌊ a i / p i ⌋ − m i n i ⌊ a i / p i ⌋ max_i\lfloor a_i/p_i \rfloor - min_i\lfloor a_i/p_i \rfloor maxiai/piminiai/pi的最小值。
    数据范围 1 ≤ k , n ≤ 3000 1 \leq k,n \leq 3000 1k,n3000 1 ≤ a 1 ≤ a 2 ⋯ a n ≤ 3000 1 \leq a_1 \leq a_2 \cdots a_n \leq 3000 1a1a2an3000

    超时的思路:对每个i预处理能够达到的数。遍历每个i考察可以达到的数并假设其为最大值,对其他所有j!=i求最后一个小于等于该值的数。

    #include 
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    
    
    
    
    int main()
    {
        int t; cin>>t;
        for(int i  =0 ;i<t;i++)
        {
            int n,k;scanf("%d%d",&n,&k);
            int a[n];for(int  o = 0;o<n;o++)scanf("%d",&a[o]);
            if(k > a[n-1] || n == 1)printf("0\n");
            else
            {
                vector<int> m[n];
                for(int i = 0;i<n;i++) for(int j = k;j>=1;j--) if(m[i].size()==0||a[i]/j>m[i][m[i].size()-1])m[i].push_back(a[i]/j); 
                int ans = INT_MAX;
                for(int i = 0;i<n;i++)
                {
                    for(int v:m[i])
                    {
                        int maximal  = v;
                        int minmax = INT_MAX;
                        bool f  = true;
                        for(int j = 0;j<n;j++)
                        {
                           
                            if(i!=j)
                            {
                                auto iter = upper_bound(m[j].begin(),m[j].end(),v);      
                                iter = prev(iter);
                                if(iter-m[j].begin()>=0) minmax=min(minmax,*iter); else {f=false;break;}
                            }
                        }
                        if(f)ans = min(ans,maximal - minmax);
                    }
                }
                printf("%d\n",ans);
            }
        }
        system("pause");
        return 0;
    }
    
    
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    原因分析:不必要的重复搜索。上述做法是遍历i,然后遍历每个v。但v的取值空间是十分有限的(最大值的取值),即使是在不同的i处,相同的v搜索结果完全一致。
    修改:直接枚举上述最大值v,其余做法相同。

    #include 
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    
    
    
    
    int main()
    {
        int t; cin>>t;
        for(int i  =0 ;i<t;i++)
        {
            int n,k;scanf("%d%d",&n,&k);
            int a[n];for(int  o = 0;o<n;o++)scanf("%d",&a[o]);
            if(k > a[n-1] || n == 1)printf("0\n");
            else
            {
                vector<int> m[n];
                for(int i = 0;i<n;i++) for(int j = k;j>=1;j--) if(m[i].size()==0||a[i]/j>m[i][m[i].size()-1])m[i].push_back(a[i]/j); 
                int ans = INT_MAX;
                for(int maximal = a[n-1]/k;maximal<=a[n-1];maximal++)
                {
                    int truemaximal = INT_MIN;
                    int minimum = INT_MAX;
                    bool f = true;
                    for(int j =  0;j<n;j++)
                    {
                        auto iter = upper_bound(m[j].begin(),m[j].end(),maximal);
                        iter = prev(iter);
                        if(iter-m[j].begin()>=0) {truemaximal = max(truemaximal,*iter);minimum=min(minimum,*iter);} else {f=false;break;}
                    }
                    if(truemaximal!=maximal) f=false;
                    if(f) {ans=min(ans,maximal - minimum);}
                }
                // cout<
                
                // for(int i = 0;i
                // {
                //     for(int v:m[i])
                //     {
                //         int maximal  = v;
                //         int minmax = INT_MAX;
                //         bool f  = true;
                //         for(int j = 0;j
                //         {
                           
                //             if(i!=j)
                //             {
                //                 auto iter = upper_bound(m[j].begin(),m[j].end(),v);      
                //                 iter = prev(iter);
                                
                //             }
                //         }
                //         if(f)ans = min(ans,maximal - minmax);
                //     }
                // }
                printf("%d\n",ans);
            }
        }
        system("pause");
        return 0;
    }
    
    
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    总结:注意如何才能避免不必要的重复搜索,可以与以前那道调和级数的题做对比。

  • 相关阅读:
    《广告学概论》期末考试试卷及答案
    Matlab图像处理-均值滤波,中值滤波和高斯滤波。
    layUI项目之(待开会议&历史会议&所有会议)
    给设计小白推荐几款笔记本电脑与工具
    【2014NOIP普及组】T4:子矩阵 试题解析
    PXE网络批量装机(centos7)
    从宏观到微观——泽攸科技ZEM系列台式扫描电子显微镜在岩石分析中的应用
    springboot 多环境配置(pom配置Profiles变量来,控制打包环境)
    华为云云耀云服务器L实例评测 | 实例评测使用之硬件参数评测:华为云云耀云服务器下的监控 glances
    【最新】TensorFlow、cuDNN、CUDA三者之间的最新版本对应及下载地址
  • 原文地址:https://blog.csdn.net/nth2000/article/details/126348043