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 }