zoukankan      html  css  js  c++  java
  • Codeforces Round #555 (Div. 3)

    贪心+模拟大法好!

    A、Reachable Numbers

    思路:简单模拟。不难发现,通过f函数运算下去的步骤数量不会很多,所以暴力模拟,只要有一个数字第二次出现break即可。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 1e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 LL n;
    30 set<LL> st;
    31 
    32 int main() {
    33     while(cin >> n) {
    34         st.clear();
    35         st.insert(n);
    36         while(1) {
    37             ++n;
    38             while(n % 10 == 0) n /= 10;
    39             if(st.count(n)) break;
    40             st.insert(n);
    41         }
    42         cout << st.size() << endl;
    43     }
    44     return 0;
    45 }
    View Code

    B、Long Number

    思路:简单贪心+模拟。为了使得替换得到的数字最大,并且替换的数字必须是连续的,我们只需找到第一个替换的数字满足 $c_i > b_i$ 作为贪心的起点,并且让$ b_i > c_i$ 作为贪心的终点,然后简单模拟一下即可。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 2e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 int n, f[10], b[maxn], c[maxn];
    30 string str, ans;
    31 bool flag;
    32 
    33 
    34 int main() {
    35     while(cin >> n) {
    36         cin >> str;
    37         ans = "";
    38         flag = false;
    39         for(int i = 0; i < n; ++i) b[i] = str[i] - '0';
    40         for(int i = 1; i <= 9; ++i) cin >> f[i];
    41         for(int i = 0; i < n; ++i) c[i] = f[b[i]];
    42         for(int i = 0; i < n; ++i) {
    43             if(!flag) {
    44                 if(b[i] < c[i]) flag = true, ans += c[i] + '0'; // 贪心起点
    45                 else ans += str[i];
    46             }else {
    47                 if(b[i] > c[i]) { // 贪心终点
    48                     for(int j = i; j < n; ++j) ans += str[j];
    49                     break;
    50                 }
    51                 else ans += c[i] + '0';
    52             }
    53         }
    54         cout << ans << endl;
    55     }
    56     return 0;
    57 }
    View Code

    C1、Increasing Subsequence (easy version)

    思路:简单模拟即可。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 2e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 int n, lt, rt, cnt, per, a[maxn];
    30 string str;
    31 
    32 int main() {
    33     while(cin >> n) {
    34         cnt = 0, per = 0;
    35         str = "";
    36         for(int i = 0; i < n; ++i) cin >> a[i];
    37         int i, j;
    38         for(i = 0, j = n - 1; i < j;) {
    39             if(a[i] > a[j]) {
    40                 if(a[j] > per) str += 'R', ++cnt, per = a[j], --j;
    41                 else if(a[i] > per) str += 'L', ++cnt, per = a[i], ++i;
    42                 else break;
    43             }else {
    44                 if(a[i] > per) str += 'L', ++cnt, per = a[i], ++i;
    45                 else if(a[j] > per) str += 'R', ++cnt, per = a[j], --j;
    46                 else break;
    47             }
    48         }
    49         if(i == j && a[j] > per) {
    50             if(2 * j >= n - 1) str += 'R', ++cnt;
    51             else str += 'L', ++cnt;
    52         }
    53         cout << cnt << endl;
    54         cout << str << endl;
    55     }
    56     return 0;
    57 }
    View Code

    C2、Increasing Subsequence (hard version)

    思路:贪心+简单模拟。①若当前两边i,j指向的数字不同,则直接贪心处理;②若当前两边i,j指向的数字相同,如何选择左边或右边呢?我们只需另外设置2个变量来比较i和j分别能延伸的长度,哪边长就贪心选哪边即可。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 2e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 int n, res1, res2, cnt, per, a[maxn];
    30 string str;
    31 bool flag;
    32 
    33 int main() {
    34     while(cin >> n) {
    35         cnt = 0, per = 0;
    36         str = "";
    37         for(int i = 0; i < n; ++i) cin >> a[i];
    38         int i, j;
    39         for(i = 0, j = n - 1; i < j;) {
    40             if(a[i] > a[j]) {
    41                 flag = false;
    42                 if(a[j] > per) str += 'R', ++cnt, per = a[j], --j, flag = true;
    43                 if(flag) continue;
    44                 if(a[i] > per) str += 'L', ++cnt, per = a[i], ++i, flag = true;
    45                 if(!flag) break;
    46             }else if(a[j] > a[i]){
    47                 flag = false;
    48                 if(a[i] > per) str += 'L', ++cnt, per = a[i], ++i, flag = true;
    49                 if(flag) continue;
    50                 if(a[j] > per) str += 'R', ++cnt, per = a[j], --j, flag = true;
    51                 if(!flag) break;
    52             }
    53             else { // equal
    54                 if(a[i] <= per) break;
    55                 res1 = res2 = 0;
    56                 for(int lt = i; lt + 1 < j && a[lt] < a[lt + 1]; ++lt, ++res1);
    57                 for(int rt = j; rt - 1 > i && a[rt - 1] > a[rt]; --rt, ++res2);
    58                 if(res1 > res2) str += 'L', ++cnt, per = a[i], ++i;
    59                 else str += 'R', ++cnt, per = a[j], --j;
    60             }
    61         }
    62         if(i == j && a[j] > per) {
    63             if(2 * j >= n - 1) str += 'R', ++cnt;
    64             else str += 'L', ++cnt;
    65         }
    66         cout << cnt << endl;
    67         cout << str << endl;
    68     }
    69     return 0;
    70 }
    View Code

    D、N Problems During K Days

    思路:简单思维+贪心。题意就是要求构造出一个含k个元素的序列满足该序列①是递增的,②其和刚好为n,③ $ a_i < a_{i + 1} le 2 a_i $。第一直觉就是先给这k个元素分别有序地填上1~k这k个数字,这样一定满足①和③条件,接着自然就想到一个"NO"点和一个"YES"点,即 $frac{k(k+1)}{2} > n $、当k==1时a[0] =n。剩下的如何分配呢?借助填补1~k这一个“顺子”(来源斗地主)的思想(若是能按“顺子”填补,则一定能满足③这个条件),我们把剩下的 $ now1 = n - frac{k(k+1)}{2} $ 分成 $ now2 = frac{now1}{k} $ 组,然后再给每个$a_i$分别都加上 now2,同样得到一个含k个元素的“顺子”(两两之差的绝对值都为1)!剩下1的个数为 $ now3 = now1 \% k $ (不超过k-1)个,为了满足条件①和③,我们从后往前依次贪心给每个 $ a_i $ 加1,加到now3个1就break!不难证明这一定满足条件③。但是!!!有个trick需要特判:也就是剩下1的个数刚好为k-1个的情况:1、当 k ==2时,若a[0]  == 1,说明a[0] * 2 = 2 < a[1] = 3(显然不成立),而其余情况一定成立;2、当 $ k geq 3 $ 时,先--a[1],++a[k - 1],这个操作不难验证也是正确的。但当 $ k == 3 $ 时,还需要检验1种特殊情况:1、3、4,因为将3减1变成2,4加1变成5后该序列为1,2,5,可知这序列一定不满足情况,其余一定能满足所有条件,这个不难验证!!!

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 1e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 LL n, k, now1, now2, now3, a[maxn];
    30 
    31 int main() {
    32     while(cin >> n >> k) {
    33         if((1LL + k) * k / 2 > n) {cout << "NO" << endl; continue;}
    34         if(k == 1) {cout << "YES
    " << n << endl; continue;}
    35         now1 = n - (1LL + k) * k / 2;
    36         now2 = now1 / k;
    37         now3 = now1 % k;
    38         for(int i = 0; i < k; ++i) a[i] = i + 1 + now2;
    39         for(int i = k - 1, num = now3; k > 0 && num; --num, --i) ++a[i];
    40 
    41         if(now3 != k - 1) {
    42             cout << "YES" << endl;
    43             for(int i = 0; i < k; ++i) cout << a[i] << " 
    "[i == k - 1];
    44         }else {
    45             if(k >= 3) --a[1], ++a[k - 1];
    46             if((k == 2 && a[0] == 1) || (k == 3 && a[1] * 2 < a[2])) cout << "NO" << endl;
    47             else {
    48                 cout << "YES" << endl;
    49                 for(int i = 0; i < k; ++i) cout << a[i] << " 
    "[i == k - 1];
    50             }
    51         }
    52     }
    53     return 0;
    54 }
    View Code

    E、Minimum Array

    思路:简单贪心。这个题用vector容器会T到飞qwq,题解是用关联式容器multiset(自动排序),其增删查的时间复杂度均为 $O(log^n) $,用起来非常简单,容易上手!注意到a数组、b数组中所有元素都小于n,那么问题求解就变得简单了:为了使得每个 $a_i$ 各自能匹配到的 $b_j$ 使得 $(a_i + b_j) \% n $ 最小,只需贪心找不小于 $ (n - a_i) $ 的最小值,因为以 $ (n - a_i) $ 为起点的$ b_j$ 和 $ a_i$ 的和取模n的余数为0,往后逐渐增加,循环一圈到 $ (n - a_i - 1) $ 达到最大;若找不到,则取容器中首个元素进行匹配,即离 $ (n-a_i) $ 左边最远的一个,不难证明此时的 $(a_i+b_j) \% n $ 是最小的。时间复杂度为 $O(nlog^n)$。

    AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <iomanip>
     8 #include <complex>
     9 #include <string>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #include <list>
    14 #include <deque>
    15 #include <queue>
    16 #include <stack>
    17 #include <bitset>
    18 using namespace std;
    19 typedef long long LL;
    20 typedef unsigned long long ULL;
    21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
    22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
    23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
    24 const double eps = 1e-6;
    25 const double PI = acos(-1.0);
    26 const int maxn = 2e5+5;
    27 const int inf = 0x3f3f3f3f;
    28 
    29 
    30 int n, a[maxn], b, pos, siz;
    31 multiset<int> st;
    32 multiset<int>::iterator it;
    33 
    34 
    35 int main() {
    36     while(~scanf("%d", &n)) {
    37         st.clear();
    38         for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
    39         for(int i = 0; i < n; ++i) scanf("%d", &b), st.insert(b);
    40         for(int i = 0; i < n; ++i) {
    41             it = st.lower_bound(n - a[i]);
    42             if(it == st.end()) it = st.begin();
    43             printf("%d%c", (a[i] + *it) % n, " 
    "[i == n - 1]);
    44             st.erase(it);
    45         }
    46     }
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    Nginx 反向代理多个后台服务端口
    微信小程序,横向布局,纵向布局
    Maven的标准settings.xml文件
    Springboot 复杂查询及SQL拼接笔记
    ElementUI 设置显示侧栏滚动条elscrollbar,隐藏横向滚动条
    让俺内牛满面的编辑器啊~
    Javascript 对话框 (遇到 Ajax Load无法加载问题)
    thinkpad s5 电源功率不足提示
    NAO机器人开发环境配置
    Choregraphe 2.8.6.23动作失效
  • 原文地址:https://www.cnblogs.com/acgoto/p/10782071.html
Copyright © 2011-2022 走看看