【L,R的特點】codeforce 822C Hacker, pack your bags!

CN_swords發表於2017-07-05
codeforce 822C     Hacker, pack your bags!

給出x,幾個區間(l,r)以及其值,選擇兩個不相交的區間,要求其和為x,並cost最小。

難點: n(區間個數)<= 2*10^5,要求兩個區間不相交。
解決方法:  均是根據L,R特點:

1.根據其中一個排序,如果對L排序,那麼在i區間前面的區間的L一定是滿足小於當前L,那麼前面的區間如果R滿足小於當前L,那麼他對

當前區間以下的區間全部不相交。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")

const double PI = acos(-1.0);
const double eps = 1e-6;
//const int INF=0x3f3f3f3f;
const LL INF = 1e18;
const LL mod = 1e9+7;
const int N=2*100005;
const int M = 2500000;

struct node{
    int l,r;
    int day;
    int cost;
    bool operator <(const node &a) const{
        return r>a.r;
    }
}a[N];
bool cmp(node a,node b){
    return a.l < b.l;
}
map<int,int> mp;
int main(){
    int n,x;
    scanf("%d%d",&n,&x);
    for(int i = 0; i < n; i++){
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].cost);
        a[i].day = a[i].r-a[i].l+1;
    }
    sort(a,a+n,cmp);
    priority_queue<node> Q;
    mp.clear();
    LL mi = INF;
    for(int i = 0; i < n; i++){
        while(!Q.empty()){
            node tmp = Q.top();
            if(tmp.r < a[i].l){
                Q.pop();
                int f = tmp.day;
                if(mp.find(f) == mp.end())
                    mp[f] = tmp.cost;
                else
                    mp[f] = min(mp[f],tmp.cost);
            }
            else
                break;
        }
        Q.push(a[i]);
        if(mp.find(x-a[i].day) == mp.end())
            continue;
        else
            mi = min(mi,(LL)mp[x-a[i].day]+(LL)a[i].cost);
    }
    if(mi == INF)
        puts("-1");
    else
        printf("%I64d\n",mi);
    return 0;
}



2. 將區間的L,R直接記錄下來,從0到最遠距離迴圈過來,同樣根據當前位置如果是R,那麼以後的L全於其不相交。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")

const double PI = acos(-1.0);
const double eps = 1e-6;
//const int INF=0x3f3f3f3f;
const LL INF = 1e18;
const LL mod = 1e9+7;
const int N = 2*1e5+10;
const int M = 2500000;

vector<pair<int,int> > l[N],r[N];
LL mp[N];
int main(){
    int n,x;
    scanf("%d%d",&n,&x);
    for(int i = 0; i < n; i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        l[a].push_back(make_pair((b-a+1),c));
        r[b].push_back(make_pair((b-a+1),c));
    }
    LL mi = INF;
    for(int i = 0; i < N; i++)
        mp[i] = INF;
    for(int i = 1; i < N; i++){
        for(int j = 0; j < l[i].size(); j++){
            if(x-l[i][j].first <= 0)
                continue;
            if(mp[x-l[i][j].first] != INF)
                mi = min(mi,mp[x-l[i][j].first]+(LL)l[i][j].second);
        }
        for(int j = 0; j < r[i].size(); j++){
            mp[r[i][j].first] = min(mp[r[i][j].first],(LL)r[i][j].second);
        }
    }
    if(mi == INF){
        puts("-1");
    }
    else
        printf("%I64d\n",mi);
    return 0;
}



3.根據二分的思想,明顯先要按照r-l+1排序,但處理出來是還是一個範圍,那麼還得將R作為第二關鍵詞排序。因為這樣對於一個L,比一個區間的R小,那麼這個區間和前面的區間都不相交,那麼如果預處理 相同(r-l+1)中字首最小值,那麼就能強行二分計算一波了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")

const double PI = acos(-1.0);
const double eps = 1e-6;
//const int INF=0x3f3f3f3f;
const LL INF = 1e18;
const LL mod = 1e9+7;
const int N=2*100005;
const int M = 2500000;

struct node{
    int l,r;
    int day;
    int cost;
    int micost;
}a[N];
bool cmp(node a,node b){
    if(a.day != b.day)
        return a.day < b.day;
    return a.r < b.r;
}
LL Binseach(int l,int r,int eday,int el){
    LL ans = INF;
    int mid;
    while(l <= r){
        mid = l+(r-l>>1);
        if(a[mid].day < eday)
            l = mid+1;
        else if(a[mid].day == eday){
            if(a[mid].r < el){
                l = mid+1;
                ans = min(ans,(LL)a[mid].micost);
            }
            else
                r = mid-1;
        }
        else
            r = mid-1;
    }
    return ans;
}
int main(){
    int n,x;
    scanf("%d%d",&n,&x);
    for(int i = 0; i < n; i++){
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].cost);
        a[i].day = a[i].r-a[i].l+1;
        a[i].micost = a[i].cost;
    }
    sort(a,a+n,cmp);
    for(int i = 1; i < n; i++){
        if(a[i].day == a[i-1].day)
            a[i].micost = min(a[i].micost,a[i-1].micost);
    }
    LL mi = INF;
    for(int i = 0; i < n; i++){
        LL ans = Binseach(0,n-1,x-a[i].day,a[i].l);
        //printf("%d %d\n",i,ans);
        mi = min(mi,(LL)ans+(LL)a[i].cost);
    }
    if(mi == INF)
        puts("-1");
    else
        printf("%I64d\n",mi);
    return 0;
}


相關文章