【AtCoder Grand Contest 040】B.Two Contests

題意

nn段區間,要把他們分到兩個不同的集合S,TS,T中,不能有剩餘,每個區間只能在一個集合裏,令SS中所有區間的交的長度爲lslsTT中所有區間的交爲ltlt,求max{ls+lt}max\{ls+lt\}

題解

找到 LL 最大的區間 pprr 最小的區間 qq,那麼只有兩種情況:
1.1. p,qp,q在同一個集合內,那麼即使把剩下的所有的區間都放到這個集合,最大值也不變,我們一定是把最長的放到另一個區間內,此時答案爲maxlen+minRmaxL+1maxlen+minR-maxL+1
2.2. p,qp,q不在同一個集合裏,那麼對於pp所在的集合,交的長度爲min{max{RimaxxL+1,0}}min\{max\{R_i-maxxL+1,0\}\},對於qq所在的集合,交的長度爲min{max{minRLi+1,0}}min\{max\{minR-L_i+1,0\}\},這個問題可以轉化爲:一個數組,每個元素包含ai,bia_i,b_il兩個參數,把這個數組分成兩部分,使得min{ai}is+min{bj}jtmin\{a_i\}_{i\in{s}}+min\{b_j\}_{j\in{t}}最大,
考慮把a_i從大到小排序,同時維護bib_i後綴最小值,每次枚舉ii即可。時間複雜度O(nlog(n))O(nlog(n))

代碼:

#include<bits/stdc++.h>

using namespace std;
const int N = 2e5+100;
struct node{
    long long a,b;
}s[N];
bool cmp(node a,node b){
    return a.a>b.a;
}
long long L[N],R[N];
long long minnore[N];//後綴最小的B
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>L[i]>>R[i];
    long long maxx=0;long long minn=1e18;
    int p,q;
    long long maxxlength=0;
    for(int i=1;i<=n;i++){
        if(L[i]>maxx){
            maxx=L[i];
            p=i;
        }
        if(R[i]<minn){
            q=i;
            minn=R[i];
        }
        maxxlength=max(maxxlength,R[i]-L[i]+1);
    }
    long long ans1=maxxlength+(minn>=maxx?minn-maxx+1:0);
    for(int i=1;i<=n;i++){
        s[i].a=max(R[i]-maxx+1,0LL);
        s[i].b=max(minn-L[i]+1,0LL);
    }
  //  for(int i=1;i<=n;i++) cout<<i<<' '<<s[i].a<<' '<<s[i].b<<endl;
    sort(s+1,s+n+1,cmp);
    minnore[n+1]=(1e18);
    for(int i=n;i>=1;i--) minnore[i]=min(minnore[i+1],s[i].b);
    long long ans2=0;
    for(int i=1;i<=n-1;i++){
        ans2=max(ans2,s[i].a+minnore[i+1]);
    }
    cout<<max(ans1,ans2)<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章