1178: [Apio2009]CONVENTION會議中心_貪心

來源:互聯網
上載者:User
1178: [Apio2009]CONVENTION會議中心 Time Limit: 15 Sec   Memory Limit: 162 MB
Submit: 824   Solved: 327
[ Submit][ Status][ Discuss] Description

Siruseri政府建造了一座新的會議中心。許多公司對租借會議中心的會堂高度興趣,他們希望能夠在裡面舉行會議。 對於一個客戶而言,僅當在開會時能夠獨自佔用整個會堂,他才會租借會堂。會議中心的銷售主管認為:最好的策略應該是將會堂租借給儘可能多的客戶。顯然,有可能存在不止一種滿足要求的策略。 例如下面的例子。總共有4個公司。他們對租借會堂發出了請求,並提出了他們所需佔用會堂的起止日期(如下表所示)。 開始日期 結束日期 公司1 4 9 公司2 9 11 公司3 13 19 公司4 10 17 上例中,最多將會堂租借給兩家公司。租借策略分別是租給公司1和公司3,或是公司2和公司3,也可以是公司1和公司4。注意會議中心一天最多租借給一個公司,所以公司1和公司2不能同時租借會議中心,因為他們在第九天重合了。 銷售主管為了公平起見,決定按照如下的程式來確定選擇何種租借策略:首先,將租借給客戶數量最多的策略作為候選,將所有的公司按照他們發出請求的順序編號。對於候選策略,將策略中的每家公司的編號按升序排列。最後,選出其中字典序最小1的候選策略作為最終的策略。 例中,會堂最終將被租借給公司1和公司3:3個候選策略是{(1,3),(2,3),(1,4)}。而在字典序中(1,3)<(1,4)<(2,3)。 你的任務是協助銷售主管確定應該將會堂租借給哪些公司。 Input

輸入的第一行有一個整數N,表示發出租借會堂申請的公司的個數。第2到第N+1行每行有2個整數。第i+1行的整數表示第i家公司申請租借的起始和終止日期。對於每個公司的申請,起始日期為不小於1的整數,終止日期為不大於10^9的整數。N≤200000 Output

輸出的第一行應有一個整數M,表示最多可以租借給多少家公司。第二行應列出M個數,表示最終將會堂租借給哪些公司。 Sample Input 4
4 9
9 11
13 19
10 17 Sample Output 2
1 3 HINT

修複資料bug,並新加資料一組By NanoApe 2016.5.11

修複後資料:JudgeOnline/upload/201605/dd.rar

Source

[ Submit][ Status][ Discuss]


去掉第二個詢問就是經典貪心,,,

現在問題是第二個要怎麼處理。。。


迴歸第一問

我們去掉所有內含項目關聯性的區間中較大的那個,對結果一定不會有影響

因為如果某個最優方案有那個大的區間,那選小的一定沒有差別

這樣我們就得到一些小區間,這些區間的左右端點都是嚴格遞增的

當我們從這些區間裡選擇最多的,兩兩不相交的區間,那就是第一問的答案了

貪心即可


考慮第二問,

對於一個區間,如果選擇它,對最優答案沒有影響,那顯然這個區間是可以選的

這樣按時間順序考慮每個區間,每次檢查這個區間選了會不會讓答案變差,如果不會,就要它

如何檢查。。

顯然,當前考慮的區間中,若有一個位置已經被覆蓋過,那這個區間一定不能選

若全部為空白,那這個區間一定包含於一個較大的空區間,記這個空區間為[i,j],記當前區間[l,r]

那麼如果我們知道[i,j]、[i,l)以及(r,j]的最優答案,就能判斷了

而之前已經處理出一些兩兩不互相包含的區間

將它們按照左端點升序排序

記Right[i]為第i個區間向右,第一個與它不相交的區間

對於[l,r],我們找出所有包含於[l,r]的區間,不斷地沿Right數組走,就能找出答案

這走法可以用倍增演算法最佳化成O(logn)


#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std; const int maxn = 4E5 + 10;const int INF = ~0U>>1;const int T = 16; int n,cnt,top,tot,L[maxn],R[maxn],L2[maxn],R2[maxn],c[maxn*T]    ,cur = 1,ans,Right[maxn][20],s[maxn],Num[maxn*2];bool Mark[maxn*T]; void Read(){    cin >> n;    for (int i = 1; i <= n; i++) {        scanf("%d%d",&L[i],&R[i]);        Num[++tot] = L[i];        Num[++tot] = R[i];    }    sort(Num + 1,Num + tot + 1);    for (int i = 2; i <= tot; i++)        if (Num[i] != Num[i-1])            Num[++cur] = Num[i];    Num[++cur] = INF;    L[0] = R[0] = cur;    for (int i = 1; i <= n; i++) {        L[i] = lower_bound(Num + 1,Num + cur + 1,L[i]) - Num;        R[i] = lower_bound(Num + 1,Num + cur + 1,R[i]) - Num;        if (R[R2[L[i]]] > R[i])            R2[L[i]] = i;    }} void Work(){    for (int i = 1; i <= cur; i++) {        if (!R2[i]) continue;        while (top && R[s[top]] >= R[R2[i]]) --top;        s[++top] = R2[i];    }    for (int i = 1; i <= top; i++)        L2[i] = L[s[i]],R2[i] = R[s[i]];    int Now = top + 1;    L2[Now] = R2[Now] = cur;    for (int i = top; i; i--) {        while (L2[Now - 1] > R2[i]) --Now;        Right[i][0] = Now;        if (Right[i][0] > top) Right[i][0] = 0;    }    for (int j = 1; j < 20; j++)        for (int i = 1; i <= top; i++)            Right[i][j] = Right[Right[i][j-1]][j-1];} int Query(int l,int r){    if (l > r) return 0;    int pl = lower_bound(L2 + 1,L2 + top + 1,l) - L2;    int pr = lower_bound(R2 + 1,R2 + top + 1,r) - R2;    if (R2[pr] > r || pr > top) --pr;    if (pl > pr) return 0;    int pos = pl,ret = 1;    for (int j = 19; j >= 0; j--) {        if (!Right[pos][j]) continue;        if (Right[pos][j] <= pr) {            ret += (1<<j);            pos = Right[pos][j];        }    }    return ret;} void pushdown(int o,int l,int r){    if (Mark[o]) {        Mark[o<<1] = Mark[o<<1|1] = 1;        int mid = (l + r) >> 1;        c[o<<1] = mid - l + 1;        c[o<<1|1] = r - mid;    }} void Modify(int o,int l,int r,int ml,int mr){    if (ml <= l && r <= mr) {        Mark[o] = 1;        c[o] = r - l + 1;        return;    }    pushdown(o,l,r);    int mid = (l + r) >> 1;    if (ml <= mid) Modify(o<<1,l,mid,ml,mr);    if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr);    if (Mark[o<<1] && Mark[o<<1|1]) Mark[o] = 1;    c[o] = c[o<<1] + c[o<<1|1];} int Lower(int o,int l,int r,int ql,int qr){    int mid = (l + r) >> 1;    if (ql <= l && r <= qr) {        if (!c[o]) return cur;        if (Mark[o]) return l;        pushdown(o,l,r);        if (c[o<<1]) return Lower(o<<1,l,mid,ql,qr);        else return Lower(o<<1|1,mid + 1,r,ql,qr);    }    pushdown(o,l,r);    int ret = cur;    if (ql <= mid) ret = min(ret,Lower(o<<1,l,mid,ql,qr));    if (ret < cur) return ret;    if (qr > mid) ret = min(ret,Lower(o<<1|1,mid+1,r,ql,qr));    return ret;} int Upper(int o,int l,int r,int ql,int qr){    int mid = (l + r) >> 1;    if (ql <= l && r <= qr) {        if (!c[o]) return 0;        if (Mark[o]) return r;        pushdown(o,l,r);        if (c[o<<1|1]) return Upper(o<<1|1,mid+1,r,ql,qr);        else return Upper(o<<1,l,mid,ql,qr);    }    pushdown(o,l,r);    int ret = 0;    if (qr > mid) ret = max(ret,Upper(o<<1|1,mid+1,r,ql,qr));    if (ret) return ret;    if (ql <= mid) ret = max(ret,Upper(o<<1,l,mid,ql,qr));    return ret;} int Sum(int o,int l,int r,int ql,int qr){    if (ql <= l && r <= qr) return c[o];    pushdown(o,l,r);    int mid = (l + r) >> 1,ret = 0;    if (ql <= mid) ret += Sum(o<<1,l,mid,ql,qr);    if (qr > mid) ret += Sum(o<<1|1,mid+1,r,ql,qr);    return ret;} int main(){    //freopen("1178.in","r",stdin);    //freopen("1178.out","w",stdout);         Read();    Work();    Modify(1,0,cur,0,0);    Modify(1,0,cur,cur,cur);    ans = Query(1,cur);    printf("%d\n",ans);    int K = 0;    for (int i = 1; i <= n; i++) {        if (Sum(1,0,cur,L[i],R[i]) > 0) continue;        int l = Upper(1,0,cur,0,L[i] - 1);        int r = Lower(1,0,cur,R[i] + 1,cur);        ++l; --r;        int Need = Query(l,r);        int suml = Query(l,L[i] - 1);        int sumr = Query(R[i] + 1,r);        if (suml + sumr + 1 == Need) {            ++K;            if (K < ans) printf("%d ",i);            else printf("%d",i);            Modify(1,0,cur,L[i],R[i]);        }    }    return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.