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\n",ans);
      printf("%d\n",len);
      for(int i=0;i<len;i++)
      {
          printf("%d ",mask[i]+1);
      }
  }
  return 0;
}
View Code

 

posted @ 2019-01-27 22:21  better46  阅读(283)  评论(0编辑  收藏  举报