codeforces round#509

博主水平不高, 只能打完$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 }
Heist


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 }
Buying a TV set

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 }
Coffee Break

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 }
Glider

之后的就不会噜

猜你喜欢

转载自www.cnblogs.com/cychester/p/9657450.html