1. 程式人生 > 其它 >Codeforces Round #787 (Div. 3) A - F 題解

Codeforces Round #787 (Div. 3) A - F 題解

傳送門

A. Food for Animals

直接找一下本身夠不夠,然後不夠再拿 c

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int a, b, c, d, e;
        cin >> a >> b >> c >> d >> e;
        d -= min(d, a);
        e -= min(b, e);
        if(c >= d + e) cout << "YES" << endl;
        else cout << "NO" << endl;
    }

    return 0;
}

B. Make It Increasing

因為只能往下除,直接從後往前找就行

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
ll num[maxn], pre[maxn];

int main()
{
    int t;
    scanf("%d", &t);
    ll len = 1ll << 33;
    while(t--)
    {
        int n;
        scanf("%d", &n);
        for(int i=0; i<n; i++) scanf("%lld", &num[i]);
        int ans = 0;
        ll pre = num[n-1] + 1;
        int f = 1;
        for(int i=n-1; i>=0 && f; i--)
        {
            while(f && num[i] >= pre)
            {
                if(num[i] == 0) f = 0;
                ans++;
                num[i] >>= 1;
            }
            pre = num[i];
        }
        printf("%d\n", f ? ans : -1);
    }

    return 0;
}

C. Detective Task

思維題,說謊的人一定是在轉折處,也就是最後一個出現的 1 和最早出現的 0 之間

直接雙指標判斷一下這個區間有多少個人就行

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
ll num[maxn], pre[maxn];

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        string s;
        cin >> s;
        int l = 0, r = s.length() - 1, len = s.length();
        while(l < len && s[l] != '0') l++;
        while(r >= 0 && s[r] != '1') r--;
        int ans = 0;
        ans = l - r + 1;
        if(r == -1) ans--;
        if(l == len) ans--;
        cout << ans << endl;
    }

    return 0;
}

D. Vertical Paths

這個題直接找路徑就行,從葉子結點往上找比較方便

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 2e5 + 10;
const ll inf = 1e17 + 10;
int top[maxn], vis[maxn], du[maxn];
stack<int>st[maxn];

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        for(int i=0; i<=n; i++) du[i] = vis[i] = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &top[i]);
            if(i == top[i]) top[i] = 0;
            du[top[i]]++;
        }
        int tp = 0;
        for(int i=1; i<=n; i++)
        {
            if(du[i]) continue;
            int now = i;
            while(now && vis[now] == 0)
            {
                st[tp].push(now);
                vis[now]++;
                now = top[now];
            }
            tp++;
        }
        printf("%d\n", tp);
        for(int i=0; i<tp; i++)
        {
            printf("%d\n", st[i].size());
            while(st[i].size())
            {
                int now = st[i].top();
                st[i].pop();
                printf("%d ", now);
            }
            printf("\n");
        }
        tp = 0; 
        printf("\n");
    }

    return 0;
}

E. Replace With the Previous, Minimize

類似於記憶化搜尋

由於是字典序從小到大,因此從左到右開始找字母,看看能不能壓到 a 去,然後記憶一下被壓過的每種字母

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 310;
const ll inf = 1e17 + 10;
int alp[maxn];

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n, k;
        cin >> n >> k;
        string s;
        cin >> s;
        if(k >= 26)
        {
            while(n--) cout << 'a';
            cout << endl;
            continue;
        }
        int len = s.length();
        for(int i=0; i<300; i++) alp[i] = 0;
        alp['a'] = 'a';
        for(int i=0; i<len && k; i++)
        {
            if(alp[s[i]]) continue;
            int now = s[i];
            while(alp[now] == 0) now--;
            int way = s[i] - now;
            if(k < way) way = k, now = s[i] - k;
            k -= way;
            way = alp[now] ? alp[now] : now;
            for(int j=now+1; j<=s[i]; j++) alp[j] = way;
        }
        for(int i=0; i<n; i++)
            s[i] = alp[s[i]] ? alp[s[i]] : s[i];
        cout << s << endl;
    }

    return 0;
}

F. Vlad and Unfinished Business

如果想要在一個樹上,要求從根出發,經過若干個點的話,最後回到根,基本想法就是從要經過的點往根遍歷,沒經過一條邊,就要代價 +2,因為一次是往下,第二次是經過了該子樹要經過的點,然後回去

所以這題就套用這個想法,把 y 也作為要經過的點,然後再減去 x 到 y 的距離,就變成最後是在 y 點停下

這題和天梯賽的 L2-3 一模一樣的想法,出題人可能打過天梯賽?

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const int maxn = 2e5 + 10;
int w[maxn], dis[maxn], top[maxn], vis[maxn];
vector<int>gra[maxn];

void bfs(int s)
{
    queue<pii>q;
    q.push(make_pair(s, 0));
    top[s] = s;
    while(q.size())
    {
        pii now = q.front();
        q.pop();
        int u = now.first;
        dis[u] = now.second;
        for(int i=0; i<gra[u].size(); i++)
        {
            int v = gra[u][i];
            if(top[v]) continue;
            top[v] = u;
            q.push(make_pair(v, now.second + 1));
        }
    }
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n, m, x, y;
        scanf("%d%d%d%d", &n, &m, &x, &y);
        for(int i=0; i<m; i++) scanf("%d", &w[i]);
        w[m++] = y;
        for(int i=1; i<n; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            gra[a].push_back(b);
            gra[b].push_back(a);
        }
        bfs(x);
        int ans = 0;
        vis[x] = 1;
        for(int i=0; i<m; i++)
        {
            int now = w[i];
            while(vis[now] == 0)
            {
                vis[now] = 1;
                ans += 2;
                now = top[now];
            }
        }
        ans -= dis[y];
        printf("%d\n", ans);

        for(int i=0; i<=n; i++)
        {
            vis[i] = top[i] = 0;
            gra[i].clear();
        }
    }
    return 0;
}

G. Sorting Pancakes

群友說是個三維 dp? 不懂