1. 程式人生 > 其它 >Codeforces Round #826 (Div. 3) F

Codeforces Round #826 (Div. 3) F

F. Multi-Colored Segments

洛谷最優解

顯然我們對於每一個線段可以分成左右兩端考慮
我們先按照l sort一遍
然後每次計算與他最近的值
我們維護兩個最大的r即可
然後每次更新
然後我們再倒著做一遍
對於每一個r 找到最近的l
然後每次更新l
我們l要記錄次大和最大 因為顏色只有相同和不同兩種
最後輸出答案的時候取min即可
其實這裡的證明並不明朗
本來我是想反著的時候還應該sort一遍的
但是比不sort更錯了
我就直接交了個不sort的 居然過了 還跑的飛快

void solve(){
    int n;cin>>n;
    vector<tuple<int,int,int,int>>v;
    for(int i=1;i<=n;i++){
        int l,r,c;cin>>l>>r>>c;
        v.push_back({l,r,c,i-1});
    }
    sort(all(v));
    int r1=-INF+1,c1=n+1,r2=-INF,c2=n+2;//r1最近 r2次近
    vector<int>a(n),b(n);
    for(int i=0;i<n;i++){
        auto [l,r,c,pos]=v[i];
        if(c1!=c){
            a[pos]=l-r1;
        }else{
            a[pos]=l-r2;
        }
        //gengxin
        if(c==c1||c==c2){
            if(c==c1){
                r1=max(r1,r);
            }else{
                r2=max(r2,r);
            }
            if(r2>r1){
                swap(r1,r2);
                swap(c1,c2);
            }
        }else{
            if(r>r2){
                r2=r;
                c2=c;
            }
            if(r2>r1){
                swap(r1,r2);
                swap(c1,c2);
            }
        }
    }
    int l1=INF,l2=INF+1;
    c1=n+1,c2=n+2;
    //sort(all(v),cmp);
    for(int i=n-1;i>=0;i--){
        auto [l,r,c,pos]=v[i];
        if(c1!=c){
            b[pos]=l1-r;
        }else{
            b[pos]=l2-r;
        }
        if(c==c1||c==c2){
            if(c==c1){
                l1=min(l1,l);
            }else{
                l2=min(l2,l);
            }
            if(l2<l1){
                swap(l1,l2);
                swap(c1,c2);
            }
        }else{
            if(l<l2){
                l2=l;
                c2=c;
            }
            if(l2<l1){
                swap(l1,l2);
                swap(c1,c2);
            }
        }
    }
    for(int i=0;i<n;i++)cout<<max(0ll,min(a[i],b[i]))<<' ';cout<<endl;
}