Codeforces 1108E2 Array and Segments (Hard version)(差分+思维)

题目链接:Array and Segments (Hard version)

题意:给定一个长度为n的序列,m个区间,从m个区间内选择一些区间内的数都减一,使得整个序列的最大值减最小值最大。

题解:利用差分的思想,并且考虑到m比较小,遍历一遍序列,当前点遇到需要改变的时候进行操作,同时更新答案。

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <deque>
 5 #include <stack>
 6 #include <cmath>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23 
24 const int N=1e5+10;
25 typedef long long ll;
26 typedef unsigned long long ull;
27 int a[N],l[N],r[N];
28 vector <int> sub[N],add[N];
29 
30 int main(){
31     int mxt=-INF,mit=INF;
32     int n,m,ans=-INF,ansid=0,cnt=0;
33     scanf("%d%d",&n,&m);
34     for(int i=1;i<=n;i++){
35         scanf("%d",&a[i]);
36         mit=min(mit,a[i]);mxt=max(mxt,a[i]);
37     }
38     ans=mxt-mit;
39     for(int i=1;i<=m;i++){
40         scanf("%d%d",&l[i],&r[i]);
41         sub[l[i]].push_back(i);
42         add[r[i]+1].push_back(i);
43     }
44     for(int i=1;i<=n;i++){
45         for(int j=0;j<sub[i].size();j++){
46             int id=sub[i][j];
47             for(int k=l[id];k<=r[id];k++) a[k]--;
48         }
49         for(int j=0;j<add[i].size();j++){
50             int id=add[i][j];
51             for(int k=l[id];k<=r[id];k++) a[k]++;
52         }
53         if(sub[i].size()||add[i].size()){
54             int mi=INF,mx=-INF;
55             for(int j=1;j<=n;j++) mi=min(mi,a[j]),mx=max(mx,a[j]);
56             if(ans<mx-mi){
57                 ans=mx-mi;
58                 ansid=i;
59             }
60         }
61     }
62     printf("%d\n",ans);
63     for(int i=1;i<=m;i++){
64         if(l[i]<=ansid&&r[i]>=ansid) cnt++;
65     }
66     printf("%d\n",cnt);
67     for(int i=1;i<=m;i++){
68         if(l[i]<=ansid&&r[i]>=ansid) printf("%d ",i);
69     }
70     return 0;
71 }
View Code

 

posted @ 2019-01-26 10:14  pavtlly  阅读(357)  评论(0编辑  收藏  举报