1. 程式人生 > >Codeforces Round #535 E2-Array and Segments (Hard version)

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

題意 但是 技術 ret 記錄 -m 習慣 ear lose

題意:

給你一個數列和一些區間,讓你選擇一些區間(選擇的區間中的數都減一),

求最後最大值與最小值的差值最大,並輸出選擇的區間

思路:

在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

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