標籤:
1217 借教室
2012年NOIP全國聯賽提高組
時間限制: 1 s 空間限制: 128000 KB 題目等級 : 鑽石 Diamond題目描述 Description
在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要
向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。
面對海量租借教室的資訊,我們自然希望編程解決這個問題。
我們需要處理接下來n天的借教室資訊,其中第i天學校有ri個教室可供租借。共有m份
訂單,每份訂單用三個正整數描述,分別為dj, sj, tj,表示某租借者需要從第sj天到第tj天租
借教室(包括第sj天和第tj天),每天需要租借dj個教室。
我們假定,租借者對教室的大小、地點沒有要求。即對於每份訂單,我們只需要每天提
供dj個教室,而它們具體是哪些教室,每天是否是相同的教室則不用考慮。
借教室的原則是先到先得,也就是說我們要按照訂單的先後順序依次為每份訂單分配教
室。如果在分配的過程中遇到一份訂單無法完全滿足,則需要停止教室的分配,通知當前申
請人修改訂單。這裡的無法滿足指從第sj天到第tj天中有至少一天剩餘的教室數量不足dj個。
現在我們需要知道,是否會有訂單無法完全滿足。如果有,需要通知哪一個申請人修改
訂單。
輸入描述 Input Description
第一行包含兩個正整數n, m,表示天數和訂單的數量。
提高組 day2
第二行包含n個正整數,其中第i個數為ri,表示第i天可用於租借的教室數量。
接下來有m行,每行包含三個正整數dj, sj, tj,表示租借的數量,租借開始、結束分別在
第幾天。
每行相鄰的兩個數之間均用一個空格隔開。天數與訂單均用從1開始的整數編號。
輸出描述 Output Description
如果所有訂單均可滿足,則輸出只有一行,包含一個整數 0。否則(訂單無法完全滿足)
輸出兩行,第一行輸出一個負整數-1,第二行輸出需要修改訂單的申請人編號。
範例輸入 Sample Input
4 3
2 5 4 3
2 1 3
3 2 4
4 2 4
範例輸出 Sample Output
-1
2
資料範圍及提示 Data Size & Hint
【輸入輸出範例說明】
classroom.out
-1
2
第 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 ≤ 105;
對於 100%的資料,有1 ≤ n, m ≤ 10^6, 0 ≤ ri, dj≤ 10^9, 1 ≤ sj≤ tj≤ n。
/*線段樹70分,裸的線段樹操作,中間需加最佳化才能AC*/#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct data{ int le,ri,zhi;}a[1000001];int n,m,v[1000001],l,ans;int c[1000001],mid,sum,r;int getint(){ int w=0,q=0; char c=getchar(); while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w;}bool find(int k){ memset(c,0,sizeof(c));sum=0; for(int i=1;i<=k;i++) c[a[i].le]+=a[i].zhi,c[a[i].ri+1]-=a[i].zhi; for(int i=1;i<=n;i++) { sum+=c[i]; if(sum>v[i]) return 0; } return 1;}int main(){ n=getint(); m=getint(); for(int i=1;i<=n;i++) v[i]=getint(); for(int i=1;i<=m;i++) { a[i].zhi=getint(); a[i].le=getint(); a[i].ri=getint(); l=1; r=m;} while(l!=r) { mid=(l+r)>>1; if(find(mid)) l=mid+1; else r=mid; } if(l==m) printf("0"); else printf("-1\n%d",l);}
/*首碼和做法*/ #include<cstdio>#include<cstring>#include<algorithm>using namespace std;int m,n,a[1000002],lr,rr,mid;long long b[1000002]={0};struct type{ int d,s,t;}tr[1000002];bool aaaa(int x){ memset(b,0,sizeof(b)); for (int i=1;i<=x;i++) b[tr[i].s]+=tr[i].d,b[tr[i].t+1]-=tr[i].d; for (int i=1;i<=n;i++) { b[i]=b[i]+b[i-1]; if (b[i]>a[i]) return 0; } return 1;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",a+i); for (int i=1;i<=m;i++) scanf("%d%d%d",&tr[i].d,&tr[i].s,&tr[i].t); lr=1; rr=m; while (lr<rr) { mid=(lr+rr)/2; if (aaaa(mid)) lr=mid+1; else rr=mid; } if (lr==m && aaaa(lr)) printf("0\n"); else printf("-1\n%d\n",lr); return 0;}
CODEVS 1217 借教室