題目描述
在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。
面對海量租借教室的資訊,我們自然希望程式設計解決這個問題。我們需要處理接下來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,第二行輸出需要修改訂單的申請人編號。
輸入輸出樣例
輸入樣例#1:
4 3
2 5 4 3
2 1 3
3 2 4
4 2 4
輸出樣例#1:
-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。
這道題目顯然可以用線段樹來做,但是如果打的醜可能會超時,但這題的正解其實是貪心,順便說一句,2023年day2的第二題,聰明的質檢員似乎也是貪心,這道題需要用到乙個比較巧妙的字首和思想,這樣說吧,假設你有一列數,然後要進行區間加法,然後詢問你某個數的值是多少?當然是可以用線段樹的,但是有沒有更加簡單的方法,這裡我們可以維護這樣乙個序列,ai,如何維護ai呢,加入要將區間l,r全部加上·乙個s,那麼只需將al加上s,ar+1(r+1為下標)減去s,那麼當我們要詢問i這個元素的值是多少時,只需求出1到i中所有的a的和即為所求,為什麼呢。分類討論一下。
假設現在某個區間l,r加上了乙個s,詢問以i為下標的元素是多少。
①i在區間l,r之前,那麼不會影響到i
②i在區間l,r之中,那麼使i這個元素的值便是原來的值加上s
③i在區間l,r之後,那麼al與ar+1抵消,不受影響。
綜上,得證。
至此,我們就找到了這樣一種方法,可以不用線段樹進行區間修改,同時也可以查詢每乙個元素的值,那麼我們嘗試將這種方法用到這道題目中,首先我們二分乙個答案,然後用上面的方法,判斷是否可行,即可。
是否可以利用這種方法,用在樹狀陣列上,使得樹狀陣列可以區間修改。
const
maxn=1000000+5;
var s,t,d,sum,a:array[0..maxn] of longint;
mid,i,j,l,r,n,m:longint;
function
pd(x:longint):boolean;
var k:longint;
begin
fillchar(sum,sizeof(sum),0);
for i:=1
to x do
begin
inc(sum[s[i]],d[i]);
dec(sum[t[i]+1],d[i]);
end;
k:=0;
for i:=1
to n do
begin
inc(k,sum[i]);
if k>a[i] then
exit(false);
end;
exit(true);
end;
begin
//assign(input,'jzoj3103.in');
//reset(input);
//assign(output,'jzoj3103.out');
//rewrite(output);
readln(n,m);
for i:=1
to n do
read(a[i]);
for i:=1
to m do
read(d[i],s[i],t[i]);
l:=1;
r:=m;
while ldo
begin
mid:=(l+r)div
2; if pd(mid) then
l:=mid+1
else
r:=mid;
end;
if r=m then
writeln(0)
else
begin
writeln(-1);
writeln(r);
end;
//close(input);
//close(output);
end.
thank you! 口胡 NOIP2011DAY1 選擇客棧
乙個長度為 n 的區間,每個位置上有顏色 ci 以及代價 vi,現在問有多少個區間 l,r 滿足 cl cr 且 l i r 使得v i p 我們只考慮每乙個點作為左端點時對答案的貢獻,我們令ne xti 表示在i左邊,離i最近,且vn exti p的那個端點,可以為i本身 那麼i這個端點對答案的貢...
NOIP 2012 Day2T2 借教室題解
題目描述 description 在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。面對海量租借教室的資訊,我們自然希望程式設計解決這個問題。我們需要處理接下來n天的借教室資訊,其中第i天學校有...
NOIP2012 DAY1 T2 國王遊戲
恰逢 h國國慶,國王邀請n位大臣來玩乙個有獎遊戲。首先,他讓每個大臣在左 右手上面分別寫下乙個整數,國王自己也在左 右手上各寫乙個整數。然後,讓這 n 位大臣排成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每位大臣獲得的金幣數分別是 排在該大臣前面的所有人的左手上的數...