前言
今天做了不少題,但是感覺都太水了,深思熟慮之下主播決定拿出兩道相對不那么水的題來說一下(其實還是很水)。
兩道問題,一道是日期問題(模擬),一道是區間合并問題。
日期差值
分析
這樣的問題其實就是模擬,但是我們可以發現在模擬的過程中需要處理年份,月份,天數,進位等情況,如果都去用if - else
嵌套去寫的話那未免太不優雅了。
所以主播帶了一種可以優雅的處理這種問題的方法。
這種方法是開始先將日期轉化成從0001-01-01
到此日期經過了多少天,隨后兩個數字相減就可以了,怎么樣,是不是很簡單。
那么我們如何來計算有多少天呢,先來試著按照每一天來枚舉,可以發現總共枚舉的話需要枚舉10000 * 355 * 100
次,算下來是三點五億,常數小的話是有可能過的,但是顯然我們不能去賭能不能過,我們來換一種方式枚舉。
怎樣枚舉呢?我們先計算出這一年的前面所有年有多少天(這個好算,枚舉每一年,平年就+355
, 閏年+356
),隨后我們再枚舉這個月前面所有的月份有多少天,用一個數組來存儲每個月有多少天,如果是2
月的話需要判斷一下年份是否是閏年。
超級簡單,沒錯,主包就是這么水……
代碼
#include<iostream>
using namespace std;
int mouths[] ={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //每月的天數
int y1, y2, m1, m2, d1, d2;bool is_leap(int year)
{return year % 4 == 0 && year % 100 || year % 400 == 0;
}int mouthDay(int year, int mouth)
{if(mouth == 2) return mouths[2] + is_leap(year);return mouths[mouth];
}int yearDay(int year)
{return 365 + is_leap(year);
} int dayNums(int year, int mouth, int day)
{int l = 0;for(int i = 1; i < year; i++)l += yearDay(i);for(int i = 1; i < mouth; i++)l += mouthDay(year, i);l += day;return l;
}int main()
{while(~scanf("%04d%02d%02d\n%04d%02d%02d", &y1, &m1, &d1, &y2, &m2, &d2))printf("%d\n", abs(dayNums(y2, m2, d2) - dayNums(y1, m1, d1)) + 1);return 0;
}
擠牛奶
分析
這個就更不用多說了,區間合并,主包記得自己最開始學算法的時候第一個真正理解的就是區間合并。
具體過程就是先排序,隨后每次都用區間去和前一個區間比較能否合并,區間能合并的條件一般是
a[i].r >= a[i].l
特殊情況可能需要左端加一再去比較(就比如我們之前的拿到水管的題目)。
順便提一嘴這道題用差分前綴和也是可以寫的。
代碼
// 區間合并
#include<iostream>
#include<vector>
#include<algorithm>
#define s second
#define f first
using namespace std;
typedef pair<int, int> PII;
const int N = 5010;
int n;
PII nums[N];
int onTime, unTime;int main()
{scanf("%d", &n);for(int i = 0; i < n; i++)scanf("%d%d", &nums[i].f, &nums[i].s);sort(nums, nums + n);vector<PII> vtr;vtr.push_back(nums[0]);for(int i = 1; i < n; i++)if(vtr.back().s >= nums[i].f) vtr[vtr.size() - 1].s = max(vtr[vtr.size() - 1].s, nums[i].s);else vtr.push_back(nums[i]);for(int i = 0; i < vtr.size(); i++)onTime = max(onTime, vtr[i].s - vtr[i].f); //int t = vtr[0].s;for(int i = 1; i < vtr.size(); i++)unTime = max(unTime, vtr[i].f - t), t = vtr[i].s;printf("%d %d", onTime, unTime);return 0;
}
總結
?主包要去休息了,實在是困得不行了,打了一天瞌睡QAQ。