zoukankan      html  css  js  c++  java
  • 51nod 1402 最大值 3级算法题 排序后修改限制点 时间复杂度O(m^2)

    代码:

    题意,第一个数为0,相邻的数相差0或者1,有一些点有限制,不大于给定值,求这组数中可能的最大的那个数。

    这题我们看一个例子:第5个数的限制为2

    1 2 3 4 5 6 7 8 9 

    0 1 2 3 2

    第一个数一定是0,那么我们可以看出其中最大的数为3。

    第二个例子:第6个数的限制为2

    1 2 3 4 5 6 7 8 9

    0 1 2 3 3 2

    其中最大的数为3。

    关于奇数和偶数,我们可以总结出一个规律

    假设左边的数的下标为left,右边的数的下标为right,左边的数为value1,右边的数为value2。

    我们可以得出其中的最大值mx = (right-left-(value2-value1))/2+value2。

    如果还是不清楚,可以画一画图,这是化简得来的。

    有了这个公式我们就好办了,每个限制点分类讨论,1.能达到限制值,2.不能达到限制值。

    最后要注意的一点是:这题有个坑

    可能后面的限制点会约束前面的限制点。

    例如:

    第3个点限制为2,第4个点限制为0

    如果只管前面的点,不顾后面的点的话,

    1 2 3 4 5

    0 1 2 0

    这样会产生矛盾,导致第3个点与第4个点差值大于1。

    所以我们需要先把限制条件处理好,

    我们把所有限制点,对其他点的约束,处理好之后,再按照最前面的公式,和分类讨论来做就可以AC了。

    我处理限制点的方法是:考虑到只有限制值小的点会对限制值大的产生影响,

                我对这些数排个序,把每个点对,比它大的点的约束修改好之后,再来算就好了。

    可能会考虑到的问题是:一个点A对后面的某个点B约束修改之后,可能不再是顺序的。

                这不是问题,因为B是被A修改来的,它不会对左边的数产生影响。

               反证法:如果能产生影响的话,说明A没有修改完所有可以改变的点,产生矛盾,所以不会对前面的点产生影响。

    代码:

    #include <bitsstdc++.h> 
    using namespace std;
    typedef long long ll;
    
    //用来排序的数组 
    struct node{
        int index;
        int value;
        int con;   //存在原数组s1中的位置 
    }s[55];
    
    
    int s1[55][2];  // 原数组,输入数据 
    
    bool cmp(node x,node y){
        if(x.value == y.value) return x.index < y.index;
        else return x.value < y.value;
    }
    
    int main() {
      int t,n,m;
      cin >> t;
      while(t--){
          cin >> n >> m;
          for(int i = 0;i < m; i++){
              cin >> s1[i][0] >> s1[i][1];
              s[i].index = s1[i][0];
              s[i].value = s1[i][1];
              s[i].con = i;
            }
          sort(s,s+m,cmp);
          for(int i = 0;i < m; i++){
              for(int j = i+1;j < m; j++){
                  if(s[i].value < s[j].value){
                      if(abs(s[j].index-s[i].index)+s[i].value < s[j].value){
                          s[j].value = abs(s[j].index-s[i].index)+s[i].value;
                          s1[s[j].con][1] = abs(s[j].index-s[i].index)+s[i].value;
                        }
                    }
                }
            }
          
          int k1,k2;
          int value = 0;int index = 1;
            int ans  = 0;
            s1[m][0] = n,s1[m][1] = 100000000;
            for(int i = 0;i <= m; i++){
              k1 = s1[i][0];k2 = s1[i][1];
              int mx = k1-index+value;
              if(mx <= k2){
                  value = mx;
                  index = k1;
                  ans = max(ans,mx);
                }else{
                    int l = k1-index+1-(k2-value)-2;
                    ans = max(ans,(l+1)/2+k2);
                    value = k2;
                    index = k1;
                }
            }
            cout << ans << endl;
        }
      return 0;
    }
    //  writen by zhangjiuding 
  • 相关阅读:
    JavaScript: RegExp + replace
    JavaScript:布局
    DOM和BOM区别
    正则表达式
    a report about the history of pragrem
    web第6次作业position
    web api
    DOM Event:事件流动(Event Flow)
    FOR衍生对象
    前端的发展
  • 原文地址:https://www.cnblogs.com/zhangjiuding/p/7637812.html
Copyright © 2011-2022 走看看