训练赛12

会慢慢把以前的几次有质量的训练赛补上,还有一些没做的题目

A - Jumping Buildings   Gym - 102302A 

题目大意:n个建筑,给你每个的高度h,你从第i个建筑最远可以跳到第min(i+hi,n)个建筑,但遇到比起跳建筑高的会停下来,问从每个建筑起跳,最多跳几个建筑。

思路:单调栈,从尾到头扫一遍,如果栈顶元素高度不比当前的高,栈顶弹出,直到遇到比当前高的建筑或者栈为空,当前建筑进栈,若进栈时栈为空,便能跳到n,否则跳到栈顶楼号-1,注意最后特判题目给定的最远到达距离。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct node {
 4     int h, k,d;
 5 };
 6 node a[100010];
 7 int main(){
 8     int n;
 9     cin >> n;
10     for (int i = 1; i <= n; i++) {
11         cin >> a[i].h;
12         a[i].k = i;
13     }
14     stack<node>q;
15     for (int i = n; i >= 1; i--) {
16         while (!q.empty()) {
17             if (q.top().h <= a[i].h)
18                 q.pop();
19             else break;
20         }
21         if (q.empty())a[i].d = n - i;
22         else
23         a[i].d = q.top().k - i-1;
24         if (a[i].d > min(a[i].h, n - i))a[i].d = min(a[i].h, n - i);
25         q.push(a[i]);
26     }
27     for (int i = 1; i <= n; i++) {
28         if (i != 1)cout << " ";
29         cout << a[i].d;
30     }
31     cout << endl;
32     return 0;
33 }

B - Divples     Gym - 102302B 

题目大意:给两个数a和b,输出同时满足是a的因数也是b的倍数的数。

思路:看起来数很大,但枚举a的因数时,一次就可以枚举2个,比如4 = 1*4,便得到了1和4,但要特别注意遇到9 = 3*3这种两个因数相同的情况,不要输出两次。用STL的set可以很好的解决这个问题。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main() {
 4     ios::sync_with_stdio(false);
 5     long long a, b,ff=0;
 6     set<long long>s1;
 7     cin >> a >> b;
 8     for (long long i = 1; i <= sqrt(a)+1; i++) {
 9         if (a % i == 0) {
10             if (a % i == 0 && i % b == 0) {
11                 s1.insert(i);
12             }
13             long long l = a / i;
14             if (a % l == 0 && l % b == 0) {
15                 s1.insert(l);
16             }
17         }
18     }
19     set<long long> ::iterator it;
20     for (it = s1.begin(); it != s1.end();++it) {
21         if (ff != 0)cout << " ";
22         cout << *it;
23         ff++;
24     }
25     return 0;
26 }

C - Rectangles     Gym - 102302C

题目大意:给你n个点,问你能组成多少种边与坐标轴平行,并且边上和内部都没有点的矩形。

思路:看起来难其实不难的模拟题,先按x和y的小于优先级排序,枚举每个点,因为边上不能有点,所以只能选取和当前点横坐标相同的第一个点和纵坐标相同的第一个点作为第2、3个点。同时第四个点

的横坐标和纵坐标要分别和第3个点、第二个点相同,在搜到第四个点前,一旦发现有点在即将组成的矩形内部,就放弃搜索。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct node{
 4     long long x, y;
 5 }a[2010];
 6 bool cmp(node a1, node a2) {
 7     if (a1.x == a2.x)return a1.y < a2.y;
 8     else return a1.x < a2.x;
 9 }
10 int main() {
11     int n,sum=0;
12     cin >> n;
13     for (int i = 0; i < n; i++)
14         cin >> a[i].x >> a[i].y;
15     sort(a, a + n, cmp);
16     for (int i = 0; i < n-1; i++) {
17         int flag = 0;
18         int y1 = a[i].y, y2=-1,x1=-1,x2=-1;
19         for (int j = i + 1; j < n; j++) {
20             if (a[j].x == a[i].x && flag == 0) {
21                 flag = 1;
22                 y2 = a[j].y;
23             }
24             else if (a[j].y == a[i].y && flag == 1) {
25                 x2 = a[j].x;
26                 flag = 2;
27             }
28             else if (a[j].x == x2 && a[j].y == y2 && flag == 2) {
29                 flag = 3; break;
30             }
31             else if (flag == 1 && a[j].y > a[i].y && a[j].y <= y2)break;
32             else if (flag == 2 && a[j].x == x2 && a[j].y < y2)break;
33         }
34         if (flag == 3)sum++;
35     }
36     cout << sum << endl;
37     return 0;
38 }

D - Guessing Messages   Gym - 102302D 

题目大意:问字符串b是否为字符串a的子序列。

思路:很简单,记录下标扫一遍就行。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main() {
 4     ios::sync_with_stdio(false);
 5     string s1, s2;
 6     cin >> s1 >> s2;
 7     int n1 = s1.length(), n2 = s2.length();
 8     int r = 0;
 9     for (int i = 0; i < n1; i++) {
10         if (s1[i] == s2[r])
11             r++;
12         if (r == n2)break;
13     }
14     if (r == n2)cout << "YES" << endl;
15     else cout << "NO" << endl;
16     return 0;
17 }

E - Chi's performance   Gym - 102302E

预处理比较麻烦的dp,待补

F - Drawing cards   Gym - 102302F

概率题,公式是(n+1.0)/2,你问我为什么?我也不知道。

I - Weird Sanchola    Gym - 102302J

题目大意:给你一个数组,让你把这个数组中所有的数变成相同的素数,每次可以把一个数变化1,问至少变化几次。

思路:我一开始以为是求距离所有数的平均数最近的素数,但这是错的,实际上是距离中位数最近的素数。。。找到中位数,分别往它左右搜,分别搜一个,取变化次数最小值。

代码:

 1 Select Code
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 long long a[100007];
 5 bool is_prime(int u)
 6 {
 7     if (u == 0 || u == 1) return false;
 8     if (u == 2 || u == 3) return true;
 9     if (u % 2 == 0) return false;
10     for (int i = 3; i <= sqrt(u); i += 2)
11     {
12         if (u % i == 0) return false;
13     }
14     return true;
15 }
16 int main(){
17     long long n,min1=1e18;
18     cin >> n;
19     long long sum=0;
20     for (int i = 0; i < n; i++) {
21         cin >> a[i];
22         sum += a[i];
23     }
24     sort(a, a + n);
25     for (long long i = a[n / 2]; i > 1;i--) {
26         long long us = 0;
27         if (is_prime(i)) {
28             for (int j = 0; j < n; j++) {
29                 us += abs(a[j] - i);
30             }
31             min1 = min(min1, us);
32             break;
33         }
34     }
35     for (long long i = a[n / 2]; i <= 1e18; i++) {
36         long long us = 0;
37         if (is_prime(i)) {
38             for (int j = 0; j < n; j++) {
39                 us += abs(a[j] - i);
40             }
41             min1 = min(min1, us);
42             break;
43         }
44     }
45       cout << min1 << endl;
46     return 0;
47 }

猜你喜欢

转载自www.cnblogs.com/Sympa/p/12900590.html