COGS 1266 借教室_線段樹

來源:互聯網
上載者:User
1266. [NOIP2012] 借教室 ★★☆   輸入檔案: classrooms.in   輸出檔案: classrooms.out    簡單對比
時間限制:1 s   記憶體限制:128 MB 【題目描述】

在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要 向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。 

面對海量租借教室的資訊,我們自然希望編程解決這個問題。 

我們需要處理接下來n天的借教室資訊,其中第i天學校有ri個教室可供租借。共有m份 訂單,每份訂單用三個正整數描述,分別為dj,sj,tj,表示某租借者需要從第sj天到第tj天租 借教室(包括第sj天和第tj天),每天需要租借dj個教室。 

我們假定,租借者對教室的大小、地點沒有要求。即對於每份訂單,我們只需要每天提 供dj個教室,而它們具體是哪些教室,每天是否是相同的教室則不用考慮。 

借教室的原則是先到先得,也就是說我們要按照訂單的先後順序依次為每份訂單分配教 室。如果在分配的過程中遇到一份訂單無法完全滿足,則需要停止教室的分配,通知當前申 請人修改訂單。這裡的無法滿足指從第sj天到第tj天中有至少一天剩餘的教室數量不足dj個。 

現在我們需要知道,是否會有訂單無法完全滿足。如果有,需要通知哪一個申請人修改 訂單。 【輸入格式】

第一行包含兩個正整數n,m,表示天數和訂單的數量。 

第二行包含n個正整數,其中第i個數為ri,表示第i天可用於租借的教室數量。 

接下來有m行,每行包含三個正整數dj,sj,tj,表示租借的數量,租借開始、結束分別在 第幾天。 

每行相鄰的兩個數之間均用一個空格隔開。天數與訂單均用從1開始的整數編號。 【輸出格式】

如果所有訂單均可滿足,則輸出只有一行,包含一個整數 0。否則(訂單無法完全滿足) 輸出兩行,第一行輸出一個負整數-1,第二行輸出需要修改訂單的申請人編號。 【範例輸入】

4 3 2 5 4 3 2 1 3 3 2 4 4 2 4 
【範例輸出】
-12
【輸入輸出範例說明】

第 1 份訂單滿足後,4 天剩餘的教室數分別為 0,3,2,3。第 2 份訂單要求第 2 天到 第 4 天每天提供 3 個教室,而第 3 天剩餘的教室數為 2,因此無法滿足。分配停止,通知第 2 個申請人修改訂單。 【資料範圍】

對於 10%的資料,有1 ≤ n,m ≤ 10; 

對於 30%的資料,有1 ≤ n,m ≤ 1000; 

對於 70%的資料,有1 ≤ n,m ≤ 10^5; 

對於 100%的資料,有1 ≤ n,m ≤ 10^6,0 ≤ ri,dj ≤ 10^9,1 ≤ sj ≤ tj ≤ n。






首先可以類比  當年考試可以45分。。。。我是蒟蒻就類比的。。


現在可以看出來這是個很裸的線段樹(裸但是不是正解)

維護最小值

查詢minv[1]

區間更新

當年可以得到85/90/95分

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int lim=1000011;int minv[lim<<2],addv[lim<<2];int m,n,x,y,w;int a,b,c;void pushup(int o){minv[o]=min(minv[o<<1],minv[o<<1|1]);}void build(int o,int l,int r){    if(l==r)    {        scanf("%d",&minv[o]);        return;    }    int m=(l+r)>>1;    build(o<<1,l,m);    build(o<<1|1,m+1,r);    pushup(o);}void pushdown(int o){    addv[o<<1]+=addv[o];    addv[o<<1|1]+=addv[o];    minv[o<<1]+=addv[o];    minv[o<<1|1]+=addv[o];    addv[o]=0;}void add(int o,int l,int r){    if(l>=x&&r<=y)    {        addv[o]+=w;        minv[o]+=w;        return;    }    pushdown(o);    int m=(l+r)>>1;    if(x<=m)add(o<<1,l,m);    if(y>m)add(o<<1|1,m+1,r);    pushup(o);}int main(){    freopen("classrooms.in","r",stdin);freopen("classrooms.out","w",stdout);    scanf("%d%d",&m,&n);    build(1,1,m);    for(a=1;a<=n;a++)    {        scanf("%d%d%d",&w,&x,&y);        w=-w;        add(1,1,m);        if(minv[1]<0)        {            cout<<-1<<'\n'<<a<<'\n';            return 0;        }    }    cout<<0<<endl;    return 0;}




可是  正解是二分。。。二分啊二分。。。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int s[1000011];struct self{int x,y,w;}g[1000011];int m,n,a,b,c,d;int l,r,mid,now;int ans;void work(int l,int r){    int a;    if(r>now)    for(a=now+1;a<=r;a++)     {        s[g[a].x]-=g[a].w;        s[g[a].y+1]+=g[a].w;    }    else    for(a=r+1;a<=now;a++)     {        s[g[a].x]+=g[a].w;        s[g[a].y+1]-=g[a].w;    }    now=r;}bool ok(){    int ret=0,a;    for(a=1;a<=m;a++)    {        ret+=s[a];        if(ret<0)return false;    }    return true;}int main(){    freopen("classrooms.in","r",stdin);    freopen("classrooms.out","w",stdout);    scanf("%d%d",&m,&n);    b=c=0;    for(a=1;a<=m;a++)    {        scanf("%d",&c);        s[a]=c-b;        b=c;    }        for(a=1;a<=n;a++)scanf("%d%d%d",&g[a].w,&g[a].x,&g[a].y);        l=1;r=m;ans=-1;    while(l<=r)    {        mid=(l+r)>>1;        work(1,mid);        if(ok())        l=mid+1;                else        {            r=mid-1;            ans=mid;        }    }    if(ans==-1)cout<<0<<endl;    else cout<<-1<<endl<<ans<<endl;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.