zoukankan      html  css  js  c++  java
  • 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(待补)

    题意:

    题解:

  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/scaulok/p/9951217.html
Copyright © 2011-2022 走看看