题目
A.Balloon Trip
题目描述
给定整数 W W W 和 B B B ,解决以下问题。
Takahashi的权重为 W [ k g ] W {\rm [kg]} W [ k g ] 。(注意单位为 k g {\rm kg} k g )
一个带有 n n n 气球的物体,当且仅当该物体的质量严格小于 n B nB n B [ g ] {\rm [g]} [ g ] 时,才会飞向天空。
让高桥飞上天空最少需要多少个气球?
思路
语法题
代码
1 2 3 4 5 6 7 8 9 10 #include <bits/stdc++.h> using namespace std;#define int long long signed main () { int x, y; cin >> x >> y; cout << 1000 * x / y + 1 ; return 0 ; }
B.Bird Watching
题目描述
N N N 有 M M M 类的鸟在天空中飞翔。
鸟类类型编号为 1 , 2 , … , M 1,2,\dots,M 1 , 2 , … , M 。
N N N 鸟的编号为 1 , 2 , … , N 1,2,\dots,N 1 , 2 , … , N , i i i 鸟的类型为 A i A_i A i ,尺寸为 B i B_i B i 。
对于每一个 k = 1 , 2 , … , M k=1,2,\dots,M k = 1 , 2 , … , M ,求出类型为 k k k 的飞鸟的平均大小。
可以保证,对于每一个 k = 1 , 2 , … , M k=1,2,\dots,M k = 1 , 2 , … , M ,至少有一只类型为 k k k 的鸟在飞行。
思路
语法题
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <bits/stdc++.h> using namespace std;#define int long long signed main () { int n, m; cin >> n >> m; vector<int > cnt1 (m + 1 , 0 ) ; vector<int > cnt2 (m + 1 , 0 ) ; for (int i = 1 ; i <= n; i++) { int x, y; cin >> x >> y; cnt1[x] += y; cnt2[x]++; } for (int i = 1 ; i <= m; i++) { cout << fixed << setprecision (7 ) << (double )cnt1[i] / (double )cnt2[i] << '\n' ; } return 0 ; }
C.Flapping Takahashi
题目描述
高桥决定乘坐热气球在天空中飞行。高桥在 0 0 0 时间处于 H H H 高度 (单位为秒), 并将从现在开始飞行 1 0 9 10^9 1 0 9 秒。
高桥可以每秒改变飞行高度 1 1 1 。然而,他不能使飞行高度 0 0 0 或更低。
换句话说,如果 F ( t ) F(t) F ( t ) 表示高桥在 t t t 时的高度,那么 F ( t ) F(t) F ( t ) 满足以下所有条件:
F ( 0 ) = H F(0) = H F ( 0 ) = H
− 1 ≤ F ( u ) − F ( t ) u − t ≤ 1 -1 \leq \dfrac{F(u) - F(t)}{u - t} \leq 1 − 1 ≤ u − t F ( u ) − F ( t ) ≤ 1 用于 0 ≤ t < u ≤ 1 0 9 0 \leq t \lt u \leq 10^9 0 ≤ t < u ≤ 1 0 9 。
F ( t ) > 0 F(t) \gt 0 F ( t ) > 0 用于 0 ≤ t ≤ 1 0 9 0 \leq t \leq 10^9 0 ≤ t ≤ 1 0 9 。
关于海拔有 N N N 目标。 i i i 第四个目标是使海拔在 t i t_i t i 时至少为 l i l_i l i , 最多为 u i u_i u i 。
高桥能否以一种实现所有目标的方式飞行?
给你提供了 T T T 测试用例;请解决其中的每一个。
思路
直接维护每次到达每个目标的时候飞行的最大和最小高度,要是这两个东西满足最小高度大于最大高度就炸了,否则就更新两者的值。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <bits/stdc++.h> using namespace std;#define int long long void solve () { int n, m; cin >> n >> m; vector<pair<int , pair<int , int >>> a (n); for (int i = 0 ; i < n; i++) { int x, y, z; cin >> x >> y >> z; a[i] = {x, {y, z}}; } int ls = 0 , minn = m, maxx = m; for (int i = 0 ; i < n; i++) { int x = a[i].first, y = a[i].second.first, z = a[i].second.second; minn -= x - ls; maxx += x - ls; minn = max ({minn, 1LL , y}); maxx = min (maxx, z); if (minn > maxx) { cout << "No" << '\n' ; return ; } ls = x; } cout << "Yes" << '\n' ; } signed main () { int T; cin >> T; while (T--) { solve (); } return 0 ; }
D.Clouds
题目描述
天空由 2000 × 2000 2000 \times 2000 2 0 0 0 × 2 0 0 0 网格表示。
当抬头看天空时,从顶部数第四行 r r r 和从左侧数第四列 c c c 的单元格被称为 ( r , c ) (r,c) ( r , c ) 。
目前,这片天空中飘浮着云 1 , 2 , … , N 1,2,\dots,N 1 , 2 , … , N 。
单元格 ( r , c ) (r,c) ( r , c ) 被云 i i i 覆盖,当且仅当它满足 U i ≤ r ≤ D i U_i \le r \le D_i U i ≤ r ≤ D i 和 L i ≤ c ≤ R i L_i \le c \le R_i L i ≤ c ≤ R i 。
对于 k = 1 , 2 , … , N k=1,2,\dots,N k = 1 , 2 , … , N , 请回答以下问题:
只从 N N N 云中移除云 k k k 。此时,天空中飘浮着 N − 1 N-1 N − 1 云。有多少个单元格没有被任何云覆盖?
思路
不要像我一样犯唐刚读完题没看数据范围就去写扫描线 然后这问题其实就没了
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <bits/stdc++.h> using namespace std;#define int long long int pre1[2222 ][2222 ], pre2[2222 ][2222 ];signed main () { int n; cin >> n; vector<vector<int >> v; for (int i = 0 ; i < n; i++) { int u, d, l, r; cin >> u >> d >> l >> r; v.push_back ({l, r, u, d}); pre1[u][l]++; pre1[u][r + 1 ]--; pre1[d + 1 ][l]--; pre1[d + 1 ][r + 1 ]++; } for (int i = 1 ; i <= 2000 ; i++) { for (int j = 1 ; j <= 2000 ; j++) { pre1[i][j] += pre1[i][j - 1 ]; } } for (int i = 1 ; i <= 2000 ; i++) { for (int j = 1 ; j <= 2000 ; j++) { pre1[i][j] += pre1[i - 1 ][j]; } } int cnt = 0 ; for (int i = 1 ; i <= 2000 ; i++) { for (int j = 1 ; j <= 2000 ; j++) { if (pre1[i][j] == 0 ) { cnt++; } } } for (int i = 1 ; i <= 2000 ; i++) { for (int j = 1 ; j <= 2000 ; j++) { pre2[i][j] = pre2[i - 1 ][j] + pre2[i][j - 1 ] - pre2[i - 1 ][j - 1 ] + ((pre1[i][j] == 1 ) ? 1 : 0 ); } } for (int i = 0 ; i < n; i++) { int l = v[i][0 ], r = v[i][1 ], u = v[i][2 ], d = v[i][3 ]; cout << cnt + pre2[d][r] - pre2[u - 1 ][r] - pre2[d][l - 1 ] + pre2[u - 1 ][l - 1 ] << '\n' ; } return 0 ; }
E.Distribute Bunnies
题目描述
在数轴上有编号为 1 1 1 到 N N N 的 N N N 只兔子。兔子 i i i 在坐标 X i X_i X i 。多个兔子可能在同一坐标。
每只兔子有一个参数叫跳跃能力 ,兔子 i i i 的跳跃功率 R i R_i R i 。
现在,所有的兔子都只跳一次。当坐标 x x x 具有跳跃能力 r r r 的兔子跳跃时,它移动到坐标 x + r x+r x + r 或坐标 x − r x-r x − r 。
如果你可以自由选择每只兔子跳跃到的坐标,找到所有兔子跳跃后兔子所在的最大可能的不同坐标。
思路
不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心不要贪心
我们可以把每一个兔子左右分别能跳到的位置离散化,并把他们在并查集中合并。所以对于每个并查集里的连通分量,能对答案产生的贡献就是边数和点数之间的最小值。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include <bits/stdc++.h> using namespace std;#define int long long struct DSU { vector<int > fa, cnt1, cnt2; DSU (int n) { fa.resize (n + 1 ); cnt1. resize (n + 1 , 1 ); cnt2. resize (n + 1 , 0 ); for (int i = 0 ; i <= n; i++) { fa[i] = i; } } int find (int x) { if (fa[x] == x) { return x; } return fa[x] = find (fa[x]); } void merge (int x, int y) { x = find (x); y = find (y); if (x != y) { fa[x] = y; cnt1[y] += cnt1[x]; cnt2[y] += cnt2[x] + 1 ; } else { cnt2[x]++; } } }; signed main () { int n; cin >> n; vector<pair<int , int >> a (n); vector<int > v; for (int i = 0 ; i < n; i++) { int x, y; cin >> x >> y; a[i] = {x - y, x + y}; v.push_back (a[i].first); v.push_back (a[i].second); } sort (v.begin (), v.end ()); v.erase (unique (v.begin (), v.end ()), v.end ()); DSU dsu (v.size()) ; for (int i = 0 ; i < n; i++) { int tp1 = lower_bound (v.begin (), v.end (), a[i].first) - v.begin (); int tp2 = lower_bound (v.begin (), v.end (), a[i].second) - v.begin (); dsu.merge (tp1, tp2); } int ans = 0 ; for (int i = 0 ; i < v.size (); i++) { if (dsu.find (i) == i) { ans += min (dsu.cnt1[i], dsu.cnt2[i]); } } cout << ans; return 0 ; }
复盘
NOIPlus诗人