Loading

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? 不懂

posted @ 2022-05-06 11:02  dgsvygd  阅读(52)  评论(0编辑  收藏  举报