博主水平不高, 只能打完$4$题, QAQ什么时候才能变强啊嘤嘤嘤
A. Heist
输出 $max - min + n - 1$即可
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 1e3 + 5; 8 const int inf = ~0U >> 1; 9 10 int n, a[N], x, maxn, minn = inf; 11 12 int read () { 13 int X = 0, p = 1; char c = getchar(); 14 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 15 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 16 return X * p; 17 } 18 19 int main() 20 { 21 n = rd; 22 for(int i = 1; i <= n; ++i) { 23 a[i] = rd; 24 minn = min(minn, a[i]); 25 maxn = max(maxn, a[i]); 26 } 27 printf("%d\n", maxn - minn - n + 1); 28 }
B. Buying a TV Set
Description
要求找出 $ i<=a, j<=b$ 并且 $ i : j = x : y$
Solution
先将$ x, y$约分, 输出$ \min(i \div x, j \div y)$ 即可
Code
1 #include<cstdio> 2 #define ll long long 3 4 ll gcd(ll x, ll y) { 5 return x % y ? gcd(y, x % y) : y; 6 } 7 8 int main() 9 { 10 ll a, b, x, y, d; 11 scanf("%I64d%I64d%I64d%I64d", &a, &b, &x, & y); 12 d = gcd(x, y); 13 x /= d; y /= d; 14 ll tmp1 = a / x, tmp2 = b / y; 15 printf("%I64d\n", tmp1 > tmp2 ? tmp2 : tmp1); 16 }
C. Coffee Break
Description
主人公想要在$n$个时间点喝咖啡, 但是老板要求他 每次 喝咖啡 的 间隔 必须 $>=d$
求问主人公至少要 几天 才能在 每个时间点 都喝过咖啡。
Solution
贪心 + 二分查找
用Set写 复杂度更严格, 但是我没想到用Set删除。
外层枚举到每一天$i$, 如果 $i$ 没有被确定在哪一天喝, 则 $++ans$, 并在第 $ans$(当前的ans) 天喝。
接下来再查找出第一个$>= \ a[i] + d + 1$的 时刻$j$, 如果$j$ 已经被确定在哪天喝, 那么$j++$, 直到$j > n $ 或 $j$ 没有被确定在哪一天喝。
把 $j$ 和 $i$ 确定为同一天喝就可以惹。
复杂度并不是严格的$O(nlogn)$, 希望不要呱
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 2e5 + 5; 8 9 int n, m, d, ans; 10 int b[N]; 11 12 struct node { 13 int pos, id, day; 14 }a[N]; 15 16 int read() { 17 int X = 0, p = 1; char c =getchar(); 18 for(;c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 19 for(;c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 20 return X * p; 21 } 22 23 int fd(int x) { 24 return lower_bound(b + 1, b + 1 + n, x) - b; 25 } 26 27 int cmp1(const node &A, const node &B) { 28 return A.pos < B.pos; 29 } 30 31 int cmp2(const node &A, const node &B) { 32 return A.id < B.id; 33 } 34 35 int main() 36 { 37 n = rd; m = rd; d = rd; 38 for(int i = 1; i <= n; ++i) 39 b[i] = a[i].pos = rd, a[i].id = i; 40 sort(b + 1, b + 1 + n); 41 sort(a + 1, a + 1 + n, cmp1); 42 for(int i = 1; i <= n; ++i) { 43 if(!a[i].day) a[i].day = ++ans; 44 int tmp = a[i].pos + d + 1; 45 tmp = fd(tmp); 46 while(a[tmp].day && tmp <= n) 47 tmp++; 48 if(tmp <= n) a[tmp].day = a[i].day; 49 } 50 printf("%d\n", ans); 51 sort(a + 1, a + 1 + n, cmp2); 52 printf("%d", a[1].day); 53 for(int i = 2; i <= n; ++i) 54 printf(" %d", a[i].day); 55 puts(""); 56 }
D. Glider
Description
求出从哪一点开始下飞机, 滑翔的水平距离最远。 在上升气流的区间内 水平飞行, 在其他地方会 $1 : 1$地 下降
并且输入的 上升气流的区间不重合、且递增。
Solution
官方题解 二分 + 前缀和。
我打出了个倍增。。。
定义$nxt[i][j]$ 为 $i$ 之后的 第 $2^j$ 个区间(这不是可以直接$O(1)$算吗??? 我怎么知道我当时怎么想的。。。
$dis[i][j]$ 为 $i$ 到 之后第 $2 ^ j$ 个区间 的空隙长度(即没有上升气流的长度)。
$sum[i] $为前 $i$ 个上升气流的总长度
由于空隙长度 必须 $ <= \ h$, 所以可以倍增求出最远到哪个区间。
然后枚举下飞机的区间, 倍增求出最远到达的区间, 前缀和查询 上升气流长度 并更新答案。
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 2e5 + 5; 8 const int base = 19; 9 10 int l[N], r[N], h, n, maxn = h, sum[N]; 11 int dis[N][20], nxt[N][20]; 12 13 int read() { 14 int X = 0, p = 1; char c = getchar(); 15 for(;c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 16 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 17 return X * p; 18 } 19 20 void cal(int now) { 21 int rest = h, tmp = now; 22 for(int k = base; ~k; --k) 23 if(nxt[tmp][k] && rest - dis[tmp][k] > 0) 24 rest -= dis[tmp][k], tmp = nxt[tmp][k]; 25 maxn = max(maxn, h + sum[tmp] - sum[now - 1]); 26 } 27 28 int main() 29 { 30 n = rd; h = rd; 31 for(int i = 1; i <= n; ++i) 32 l[i] = rd, r[i] = rd; 33 for(int i = 1; i <= n; ++i) 34 sum[i] = sum[i - 1] + r[i] - l[i]; 35 for(int i = 1; i < n; ++i) { 36 dis[i][0] = l[i + 1] - r[i]; 37 nxt[i][0] = i + 1; 38 } 39 for(int k = 1; k <= base; ++k) 40 for(int i = 1; i <= n; ++i) { 41 nxt[i][k] = nxt[nxt[i][k - 1]][k - 1]; 42 dis[i][k] = dis[i][k - 1] + dis[nxt[i][k - 1]][k - 1]; 43 } 44 for(int i = 1; i <= n; ++i) cal(i); 45 printf("%d\n", maxn); 46 }
之后的就不会噜