[NOIP2012] 借教室
【題目描述】
在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要 向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。
面對海量租借教室的信息,我們自然希望編程解決這個問題。
我們需要處理接下來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
【樣例輸出】
-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 ≤ 10^5;
對於 100%的數據,有1 ≤ n,m ≤ 10^6,0 ≤ ri,dj ≤ 10^9,1 ≤ sj ≤ tj ≤ n。
思路{
區間操作,想到了高級數據結構。。。。。。線段樹,分塊,但是我腦袋一抽用了差分。
我們通過差分可以輕易算出每天的需求是多少。然而並不是求這個,但可以作為判斷依據。
設f(x)為前x個操作的正確與否。易得,他是非嚴格單調的。故二分。
可得復雜度為O(nlogn)很神奇。
然而二分返回的L,R要註意;L為max時說明都滿足,
否則,輸出L。
}
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<ctime> 8 #include<cmath> 9 #include<list> 10 #include<deque> 11 #include<stack> 12 #include<map> 13 #include<set> 14 #define RG register 15 #define LL long long 16 #define dd double 17 #define maxx 1000002 18 using namespace std; 19 struct matrix{ 20 int s,t,d; 21 matrix() {} 22 matrix(int _d,int _s,int _t):s(_s),t(_t),d(_d) {} 23 }ask[maxx]; 24 int n,m,T[maxx],r[maxx],a[maxx]; 25 int main(){ 26 scanf("%d%d",&n,&m);int x,y,z; 27 for(RG int i=1;i<=n;++i)scanf("%d",&r[i]); 28 for(RG int i=1;i<=m;++i)scanf("%d%d%d",&x,&y,&z),ask[i]=matrix(x,y,z); 29 int L=0,R=m+1; 30 while(L<=R){ 31 int mid=(L+R)>>1; 32 memset(T,0,sizeof(T)); 33 memset(a,0,sizeof(a));bool flag=true; 34 for(RG int i=1;i<=mid;++i)T[ask[i].s]+=ask[i].d,T[ask[i].t+1]-=ask[i].d; 35 int x=0;for(RG int i=1;i<=n;++i){x+=T[i];a[i]=x;if(a[i]>r[i])R=mid-1,flag=false;} 36 if(flag)L=mid+1; 37 }if(L>m+1)cout<<"0\n",exit(0); 38 cout<<"-1\n"<<L; 39 return 0; 40 }
[NOIP2012] 借教室