題目描述
一共存在有 m 個事件,且事件分爲以下的 33 種類型。
- 小 Z 得到了 a 元壓歲錢。
- 小 Z 花掉了 a 元壓歲錢用於買皮膚。
- 小 Z 把自己的 a 元錢封印了起來,只有當第 b 個事件發生前 11 秒纔會解除封印,並保證每次小 Z 現有的錢大於等於封印的錢。
當小 Z 的錢在某個事件不夠花時,小 Z 會感到不開心,同時錢不夠花時小 Z 便不會花錢。
請告訴小 Z ,他的錢在幾個事件中會不夠花。
輸入格式
第一行一個整數 mm,用於表示事件發生的總數。
接下來的 mm 行,首先一個整數 t,表示事件的類型。
如果 t=1 或 t=2,則接下來一個整數 a。
如果 t=3,則接下來兩個整數 a,b。
輸出格式
一行一個整數,表示錢不夠花的事件數。
輸入輸出樣例
輸入 #1複製
3
1 10
2 20
2 10
輸出 #1複製
1
輸入 #2
5
1 10
3 5 5
2 10
1 10
2 20
輸出 #2
1
解答:(思路簡單,但有值得總結的地方)
思路就是直接模擬,很簡單,沒什麼好說的,代碼如下:
/*分析:先存入的錢有可能後使用,所以要用東西依照 b 升序存起來
思路:直接模擬
步驟:1.讀入數據,然後遍歷
2.依據種類進行處理
3.用一個數存當前時刻現有的錢(可能存在取出來的錢),以及需要的錢
4.用 num 記錄結果。*/
#include <cstdio>
#include <utility>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
struct cmp{
bool operator()(pair<int,int> a,pair<int,int> b){
return a.second > b.second;
}
};
int main()
{
//讀入數據:
int n;
scanf("%d",&n);
//遍歷:
LL total = 0;
int num = 0;
priority_queue<pair<int,int>,vector<pair<int,int> >,cmp> pq;
//前者代表金額,後者代表可取出的時候
for(int i = 1;i <= n;i++){
int type; //種類
scanf("%d",&type);
while(!pq.empty()&&pq.top().second == i){
total += pq.top().first;
pq.pop();
}
switch(type){
case 1:{
int a;
scanf("%d",&a);
total += a;
break;
}
case 2:{
int need;
scanf("%d",&need);
if(total >= need) total -= need;
else num++;
break;
}
case 3:{
pair<int,int> temp;
scanf("%d %d",&temp.first,&temp.second);
total -= temp.first;
pq.push(temp);
break;
}
}
}
//輸出:
printf("%d",num);
return 0;
}
總結:
這道題我錯在了,題目給的數據規模是 a <= 10^7,當時我心裏想了一下會不會爆 int,但是我又想它只是加,並且還有花錢的時候,所以沒有用 long long 類型。最後才發現,如果不用 long long 只能得60分。
其實這個問題也是自己的老問題了,就是習慣性的省空間,這個習慣在我目前應對的 oi 中還是聽不好的習慣。我還是應該以自己最有把握的想法寫出來(只要自己能力可以實現)。因爲一場比賽不一定所有題都會做,甚至對於我會有好幾道寫不全,所以更不應該在自己有把握的題上吝嗇時間和代碼。
正如這道題,我多考慮了一下可能會有先存後區的情況,所以我用了 priority_queue 以避免這種情況(雖然最終數據中好像沒有這樣的情況),但是正如上面 long long 的問題,只要是自己想到的,並且自己可以實現的就不要怕麻煩和浪費時間。因爲對於自己不會做的,多給些時間也很有可能做不出來。