• Codeforces Round #535 E2-Array and Segments (Hard version)


    Codeforces Round #535 E2-Array and Segments (Hard version)

    题意:

     给你一个数列和一些区间,让你选择一些区间(选择的区间中的数都减一),

    求最后最大值与最小值的差值最大,并输出选择的区间

    思路:

    在n=300的时候,我们是枚举每个数作为最小值,应用所有覆盖它的区间,并且没

    次都更行差值的最大值。

    但是这里的n=1e5,所以我们不能用O(n*n*m),但是我们看到这里的m=300

    所以可以从m入手,枚举区间,就是记录每个区间的两个端点,利用差分的思想,

    来枚举更新最大值

    这里说一下为什么枚举最小值,因为如果最大值也在这个区间则抵消,如果没在则

    更好

    #include<bits/stdc++.h>
    using namespace std;
    #define MAX 100005
    int n,m;
    vector<int>add[MAX],sub[MAX],a(MAX);
    vector<pair<int,int > >b(MAX);
    
    void change(int l,int r,int x)
    {
        for(int i=l;i<=r;i++)
        {
            a[i]+=x;
        }
    }
    int main()
    {
      while(~scanf("%d %d",&n,&m))
      {
          for(int i=0;i<m;i++) sub[i].clear();
          for(int i=0;i<m;i++) add[i].clear();
          for(int i=0;i<n;i++)
          {
              scanf("%d",&a[i]);
          }
          for(int i=0;i<m;i++)
          {
              scanf("%d %d",&b[i].first,&b[i].second);
              b[i].first--;
              b[i].second--;
              sub[b[i].first].push_back(i);
              add[b[i].second+1].push_back(i);
          }
          int minn,maxn;
           minn=maxn=a[0];//注意这里不要习惯把minn=INF,maxn=0,因为a数组元素可能为负数,比如-1,这样ans=1,容易出错
          for(int i=1;i<n;i++)
          {
              maxn=max(maxn,a[i]);
              minn=min(minn,a[i]);
          }
          int ans=maxn-minn;
          int c=-1;
          for(int i=0;i<n;i++)
          {
              //应用覆盖的区间
              for(int j=0;j<sub[i].size();j++)
              {
                  int ind=sub[i][j];
                  change(b[ind].first,b[ind].second,-1);
              }
              //消除之前的区间
              for(int j=0;j<add[i].size();j++)
              {
                  int ind=add[i][j];
                  change(b[ind].first,b[ind].second,1);
              }
              int minn=maxn=a[0];
              if(add[i].size()||sub[i].size())
              {
                  for(int j=1;j<n;j++)
                  {
                      maxn=max(maxn,a[j]);
                      minn=min(minn,a[j]);
                  }
                  if(maxn-minn>ans)
                  {
                      ans=maxn-minn;
                      c=i;
                  }
              }
          }
          int len=0;
          int mask[MAX];
          for(int i=0;i<m;i++)
          {
              if(b[i].first<=c&&c<=b[i].second)
              {
                  mask[len++]=i;
              }
          }
          printf("%d
    ",ans);
          printf("%d
    ",len);
          for(int i=0;i<len;i++)
          {
              printf("%d ",mask[i]+1);
          }
      }
      return 0;
    }
    View Code
  • 相关阅读:
    java实现九九乘法表
    for循环的阶乘
    Struts2 表单提交与execute()方法的结合使用
    Struts2 第三个程序 namespacce的用法
    java 字符串的比较compareTo
    java中的位预算
    java调用C++ DLL库方法
    Socket编程模式理解与对比
    c 高级函数的简单用法
    TCP粘包分析与处理
  • 原文地址:https://www.cnblogs.com/zhgyki/p/10328239.html
Copyright © 2020-2023  润新知