1. 程式人生 > >[NOIP2012] 借教室

[NOIP2012] 借教室

+= 每天 vector 一行 人的 efi 數據 返回 ret

【題目描述】

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

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

我們需要處理接下來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] 借教室