• Codeforces Educational Codeforces Round 54 题解


    题目链接:https://codeforc.es/contest/1076

    A. Minimizing the String

    题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串。

    题解:若存在一个位置 i 满足 a[i] > a[i+1],若不删除 a[i] 则后续操作不可能更优。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 2e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 char s[MAXN];
    17 
    18 int main() {
    19 #ifdef local
    20     freopen("data.txt", "r", stdin);
    21 //    freopen("data.txt", "w", stdout);
    22 #endif
    23     int n;
    24     scanf("%d%s",&n,s);
    25     int pos = n - 1;
    26     for(int i = 0; i < n - 1; i++) {
    27         if(s[i] > s[i + 1]) {
    28             pos = i;
    29             break;
    30         }
    31     }
    32     for(int i = 0; i < n; i++)
    33         if(i != pos) printf("%c",s[i]);
    34     return 0;
    35 }
    View Code

    B. Divisor Subtraction

    题意:对于一个 n,每次减去它的最小质因子直到为 0,求操作次数。

    题解:n <= 1e10,所以先筛出 1e5 以内的质因子,然后暴力找最小质因子,当最小质因子为 2 的时候,已经不存在更小的质因子,直接跳出循环即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 2e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 bool check[MAXN];
    17 int prime[MAXN];
    18 int tot;
    19 
    20 void init() {
    21     mst(check, false);
    22     tot = 0;
    23     for(int i = 2; i <= 1e5; i++) {
    24         if(!check[i]) prime[tot++] = i;
    25         for(int j = 0; j < tot; j++) {
    26             if(i * prime[j] > 1e5) break;
    27             check[i * prime[j]] = true;
    28             if(i % prime[j] == 0) break;
    29         }
    30     }
    31 }
    32 
    33 int main() {
    34 #ifdef local
    35     freopen("data.txt", "r", stdin);
    36 //    freopen("data.txt", "w", stdout);
    37 #endif
    38     init();
    39     ll n;
    40     scanf("%lld",&n);
    41     ll ans = 0;
    42     while(n) {
    43         bool flag = false;
    44         for(int i = 0; i < tot && n >= prime[i]; i++) {
    45             if(n % prime[i] == 0) {
    46                 if(prime[i] == 2) {
    47                     flag = true;
    48                     ans += n / 2;
    49                     n = 0;
    50                     break;
    51                 }
    52                 n -= prime[i];
    53                 ans++;
    54                 flag = true;
    55                 break;
    56             }
    57         }
    58         if(!flag) {
    59             ans++;
    60             break;
    61         }
    62     }
    63     printf("%lld
    ",ans);
    64     return 0;
    65 }
    View Code

    C. Meme Problem

    题意:给出一个 d,求是否存在 a + b = d 且 ab = d。

    题解:解一元二次方程,判一下无解的条件即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 2e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 
    17 
    18 int main() {
    19 #ifdef local
    20     freopen("data.txt", "r", stdin);
    21 //    freopen("data.txt", "w", stdout);
    22 #endif
    23     int t;
    24     cin >> t;
    25     while(t--) {
    26         int d;
    27         cin >> d;
    28         if(d < 4 && d != 0) {
    29             cout << "N" << endl;
    30             continue;
    31         }
    32         cout << "Y ";
    33         long double a = sqrt(((long double)d * d - 4.0 * (long double)d) / 4.0) + (long double)d / 2.0;
    34         long double b = (long double)d - a;
    35         cout << fixed << setprecision(10) << a << ' ';
    36         cout << fixed << setprecision(10) << b << endl;
    37     }
    38     return 0;
    39 }
    View Code

    D. Edge Deletion

    题意:给出一个 n 个点 m 条边的图,问最多保留 k 条边的情况下,起点 1 到每个点的最短路不变的最多有多少个,输出保留的边。

    题解:先对起点 1 跑一遍 dij,因为 n - 1 条边可以构成图的最短路,每条边产生对一个点的最短路,故跑 dij 时记录一下走当前这个点的边,跑 dfs 按顺序输出结果即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 3e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 
    17 struct edge {
    18     int v,w,id;
    19 };
    20 
    21 vector<edge>g[MAXN];
    22 bool vis[MAXN];
    23 ll dis[MAXN];
    24 vector<int>ans;
    25 pii add[MAXN];
    26 
    27 void dij(int s, int n) {
    28     ll inf2 = 1e16;
    29     for(int i = 1; i <= n; ++i)
    30         dis[i] = inf2, vis[i] = 0;
    31     dis[s] = 0;
    32     priority_queue<pair<ll, int> >q;
    33     q.push(mp(0, s));
    34     for(; !q.empty();) {
    35         int u = q.top().second;
    36         q.pop();
    37         if(vis[u]) continue;
    38         vis[u] = 1;
    39         for(int j = 0, sz = g[u].size(); j < sz; ++j) {
    40             int v = g[u][j].v;
    41             int w = g[u][j].w;
    42             int id = g[u][j].id;
    43             if(dis[v] > dis[u] + w) {
    44                 add[v] = mp(u,id);
    45                 dis[v] = dis[u] + w;
    46                 q.push(mp(-dis[v], v));
    47             }
    48         }
    49     }
    50 }
    51 
    52 vector<pii>vec[MAXN];
    53 int tot;
    54 
    55 void dfs(int u) {
    56     vis[u] = true;
    57     for(int i = 0; i < vec[u].size() && tot; i++) {
    58         int v = vec[u][i].first, id = vec[u][i].second;
    59         if(vis[v]) continue;
    60         printf("%d ",id);
    61         tot--;
    62         dfs(v);
    63     }
    64 }
    65 
    66 int main() {
    67 #ifdef local
    68     freopen("data.txt", "r", stdin);
    69 //    freopen("data.txt", "w", stdout);
    70 #endif
    71     int n,m,k;
    72     scanf("%d%d%d",&n,&m,&k);
    73     for(int i = 1; i <= m; i++) {
    74         int u,v,w;
    75         scanf("%d%d%d",&u,&v,&w);
    76         g[u].pb({v,w,i});
    77         g[v].pb({u,w,i});
    78     }
    79     dij(1,n);
    80     for(int i = 2; i <= n; i++) {
    81         vec[i].push_back(mp(add[i].first,add[i].second));
    82         vec[add[i].first].push_back(mp(i,add[i].second));
    83     }
    84     tot = min(n - 1,k);
    85     printf("%d
    ",min(n - 1,k));
    86     mst(vis, false);
    87     dfs(1);
    88     return 0;
    89 }
    View Code

    E. Vasya and a Tree

    题意:有一棵 n 个点的树,有 m 次操作(v,d,x),每次将以 v 为根且距离 v <= d 的点加上权值 x(初始权值为0),输出最后每个点的权值。

    题解:考虑离线操作,把每个点作为根的操作存起来,dfs 记录当前深度所增加的权值,对于不可到达的深度,用一个数组来记录要减去的值,差分的思想,详见代码~

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 3e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 vector<int>vec[MAXN];
    17 vector<pii>q[MAXN];
    18 
    19 
    20 int h = -1;
    21 ll ans[MAXN],dep[MAXN],now = 0;
    22 
    23 void dfs(int u,int fa) {
    24     h++;
    25     now += dep[h];
    26     for(int i = 0; i < q[u].size(); i++) {
    27         int d = q[u][i].first, x = q[u][i].second;
    28         now += x;
    29         if(h + d + 1 < MAXN) dep[h + d + 1] -= x;
    30     }
    31 //    cout << u << " " << fa << ":" << now << endl;
    32     ans[u] += now;
    33     for(int i = 0; i < vec[u].size(); i++) {
    34         int v = vec[u][i];
    35         if(v == fa) continue;
    36         dfs(v,u);
    37     }
    38     for(int i = 0; i < q[u].size(); i++) {
    39         int d = q[u][i].first, x = q[u][i].second;
    40         now -= x;
    41         if(h + d + 1 < MAXN) dep[h + d + 1] += x;
    42     }
    43     now -= dep[h];
    44     h--;
    45 }
    46 
    47 int main() {
    48 #ifdef local
    49     freopen("data.txt", "r", stdin);
    50 //    freopen("data.txt", "w", stdout);
    51 #endif
    52     int n;
    53     scanf("%d",&n);
    54     for(int i = 1; i < n; i++) {
    55         int u,v;
    56         scanf("%d%d",&u,&v);
    57         vec[u].push_back(v);
    58         vec[v].push_back(u);
    59     }
    60     int m;
    61     scanf("%d",&m);
    62     while(m--) {
    63         int v,d,x;
    64         scanf("%d%d%d",&v,&d,&x);
    65         q[v].push_back(mp(d,x));
    66     }
    67     dfs(1,0);
    68     for(int i = 1; i <= n; i++)
    69         printf("%lld ",ans[i]);
    70     return 0;
    71 }
    View Code

    F. Summer Practice Report

    题意:一本书有 n 页,每页有 xi 个 0 和 yi 个 1,问存不存在每页的数字构成一个序列,连起来之后最多连续的 0 和 1 不超过 k。

    题解:记录每一页组成序列之后,连续 1 和连续 0 的最小值,转移即可。因为一页中连续的 1 最多 k 个,所以可容纳的 0 的个数为 pre0 + k * x,记录这个数是否大于 0 即可判断是否合法,1 也同理。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define mp(a,b) make_pair(a,b)
     7 #define pi acos(-1)
     8 #define pii pair<int,int>
     9 #define pb push_back
    10 const int INF = 0x3f3f3f3f;
    11 const double eps = 1e-6;
    12 const int MAXN = 3e5 + 10;
    13 const int MAXM = 2e5 + 10;
    14 const ll mod = 1e9 + 7;
    15 
    16 ll x[MAXN],y[MAXN];
    17 
    18 int main() {
    19 #ifdef local
    20     freopen("data.txt", "r", stdin);
    21 //    freopen("data.txt", "w", stdout);
    22 #endif
    23     int n;
    24     ll k;
    25     scanf("%d%lld",&n,&k);
    26     for(int i = 1; i <= n; i++) scanf("%lld",&x[i]);
    27     for(int i = 1; i <= n; i++) scanf("%lld",&y[i]);
    28     ll nowx = -k, nowy = -k;
    29     for(int i = 1; i <= n; i++) {
    30         nowx += x[i] - y[i] * k;
    31         nowy += y[i] - x[i] * k;
    32         if(nowx < -k) nowx = -k;
    33         if(nowy < -k) nowy = -k;
    34         if(nowx > 0 || nowy > 0) {
    35             puts("NO");
    36             return 0;
    37         }
    38     }
    39     puts("YES");
    40     return 0;
    41 }
    View Code

    G. Array Game(待补)

    题意:

    题解:

  • 相关阅读:
    QBoxLayout中setSpacing(int)和addSpacing(int)的区别
    BZOJ1017 树形DP
    树形DP 2415HDU
    树形DP基础题 HDU1520
    最小生成树个数 并查集压缩路径
    伸展树基本概念基本题目
    BZOJ1010单调性DP优化
    BZOJ1009 矩阵快速幂+DP+KMP
    字典树(数组实现)
    poj 1611 The Suspects(并查集输出集合个数)
  • 原文地址:https://www.cnblogs.com/scaulok/p/9951217.html
Copyright © 2020-2023  润新知