给一个长度为n的数组,和m个区间。
每当你选择一个区间,数组中该区间内的数值全部减1,每个区间最多选一次。
问数组内元素的差值(最大值-最小值)最大是多少。
注意事项:
离散化分块。
这里离散化遇到了问题,假如某个区间的左右端点相同(长度为1),那么去重时会把该区间删除掉。
所以,可以将题目给定的 [l,r] 改为 [l,r+1) 再进行离散化。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fir first
#define sec second
using namespace std;
const int N = 1e5+100;
const int M = 500;
struct node{
int maxx,minn;
}s[3*M],s2[3*M];
int a[N];
pii seg[M];
int main() {
//freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int n,m;
cin>>n>>m;
for(int i = 1; i <= n; i++) cin>>a[i];
vector<int> k;
for(int i = 1; i <= m; i++) { //离散化
int l,r;
cin>>l>>r;
r++;
seg[i].fir = l;
seg[i].sec = r;
k.push_back(l);
k.push_back(r);
}
k.push_back(1);
k.push_back(n+1);
sort(k.begin(),k.end());
k.erase(unique(k.begin(),k.end()),k.end());
for(int i = 0; i < k.size()-1; i++) { //记录每个块的最大值和最小值
int maxx = -1e9;
int minn = 1e9;
for(int j = k[i]; j < k[i+1]; j++) {
maxx = max(maxx,a[j]);
minn = min(minn,a[j]);
}
s[i].maxx = maxx;
s[i].minn = minn;
}
int tot = k.size();
for(int i = 0; i < tot+10;i ++) s2[i] = s[i];
int ans = 0;
vector<int>need;
for(int i = 0; i < k.size()-1; i++) { //枚举答案的最小值在哪个块内
vector<int>p;
for(int j = 0; j < tot+10;j ++) s[j] = s2[j];
for(int j = 1; j <= m; j++) {
int l = lower_bound(k.begin(),k.end(),seg[j].fir)-k.begin();
int r = lower_bound(k.begin(),k.end(),seg[j].sec)-k.begin();
if(l<=i&&r>i) { //所有包括这个块的区间全选,不包括的全不选
p.push_back(j);
for(int t = l; t < r; t++) {
s[t].minn-=1;
s[t].maxx-=1;
}
}
}
int maxx = -1e9;
for(int j = 0; j < k.size()-1; j++) maxx = max(maxx,s[j].maxx); //找最大值
if(maxx-s[i].minn>=ans) {
ans = maxx-s[i].minn;
need.clear();
for(auto x:p) need.push_back(x);
}
}
printf("%d\n%d\n",ans,need.size());
for(auto x:need) printf("%d ",x);
return 0;
}