[題解]NOIP2018 Day1 Solution - by xyz32768
阿新 • • 發佈:2018-11-23
Rifkunatif thia ofa ck nweed ninck ova def
Epalts n ikwa offnet nazrot la pa
Olivazes unatifa ah kfafc fffak fjakfg
Orz zzq ak ioi
(火星文)
——《Ydjadf fha de NOIP 2018》
Day 1 T1 鋪設道路 road
演算法:模擬
- NOIP 2013 原題
- 答案為
- 證明略
- 複雜度
程式碼
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
inline int read()
{
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
typedef long long ll;
const int N = 1e5 + 5;
int n, a[N];
ll ans;
int main()
{
int i;
n = read();
For (i, 1, n) a[i] = read();
ans = a[n];
For (i, 1, n - 1) if (a[i] > a[i + 1])
ans += a[i] - a[i + 1];
std::cout << ans << std::endl;
return 0;
}
Day1 T2 貨幣系統 money
演算法:完全揹包
- 顯然,如果一種貨幣會被面額小於它自己的貨幣表出,那麼這種貨幣就沒有使用的必要
- 所以將所有貨幣按照面額為關鍵字從小到大排序後,進行完全揹包 DP
- 如果某種貨幣不能被它之前的貨幣表出,則統計入答案
- 否則這種貨幣沒有使用的必要
- 複雜度
程式碼
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
inline int read()
{
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 105, M = 25005;
int n, a[N], ans;
bool f[M];
void work()
{
int i, j;
n = read();
For (i, 1, n) a[i] = read();
std::sort(a + 1, a + n + 1);
memset(f, 0, sizeof(f));
f[0] = 1;
ans = 0;
For (i, 1, n)
{
if (!f[a[i]]) ans++;
For (j, a[i], 25000)
f[j] |= f[j - a[i]];
}
printf("%d\n", ans);
}
int main()
{
int T = read();
while (T--) work();
return 0;
}
Day1 T3 賽道修建 track
演算法:二分答案 + DP + 貪心
- 看到最小化最大值,很直觀地想到二分
- 問題轉化成是否能在樹上選出至少 條邊不相交的長度至少為 的鏈
- 令 表示 的子樹內最多能選出的鏈數
- 表示 的子樹內在選出鏈數最多的前提下,從 向下延伸的最長鏈長度
- 一個結論:在全域性最優方案中,對於任何一個 , 的子樹內選出的鏈數量需要達到最大值
- 證明:如果 的子樹內選出的鏈數量沒有達到最大值,那麼嘗試把 的子樹內的方案改成選出的鏈數更大的方案,那麼 的子樹外的貢獻最多減 ,這樣答案一定不會更劣
- 於是轉移方程出來了
- 為邊 的長度
- 表示有一個長度為 的陣列
- 其中 的第 個元素為 ( 為 的第 個子節點)
- 表示 陣列中最多能分出多少個大小在 內的集合
- 一個數能被分到一個集合,當且僅當這個數
- 兩個數能被分到一個集合,當且僅當這兩個數之和
然後你可以寫一個二分圖最大匹配做到 O(n^2logn) 的優秀複雜度- 考慮貪心匹配
- 先把 排序
- 先把 中不小於 的數各自獨立分到一個集合
- 然後小於 的數貪心兩兩匹配
- 用 two-pointers 和 ,初始 ( 為 中小於 的數的個數)
- 如果