ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #805 (Div. 3) A - G

2022-07-13 20:01:31  阅读:121  来源: 互联网

标签:10 const int ll Codeforces maxn Div include 805


传送门

第一次赛中 AK div3,值得纪念!

赛后发现有很多题想的不是很周到,所以晚发了这么久

A - Round Down the Price

找到一个不大于当前数字的 10 的次幂

#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--)
    {
        ll n;
        cin >> n;
        ll now = 1;
        while(now <= n) now *= 10;
        cout << n - (now / 10) << endl;
    }
    return 0;
}

B. Polycarp Writes a String from Memory

强行模拟一下就好了

#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 vis[310];

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        string s;
        cin >> s;
        int ans = 1, cnt = 0;
        for(int i='a'; i<='z'; i++) vis[i] = 0;
        for(int i=0; i<s.length(); i++)
        {
            cnt += ++vis[s[i]] == 1;
            if(cnt == 4)
            {
                ans++;
                cnt = 1;
                for(int i='a'; i<='z'; i++) vis[i] = 0;
                vis[s[i]] = 1;
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

C. Train and Queries

记录一下每个站最早出现的位置和最晚出现的位置,就可以判断一个站台 a 后面是否有存在另一个站台 b

#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 num[maxn];
map<int, int>l, r;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        l.clear();
        r.clear();
        for(int i=1; i<=n; i++) scanf("%d", &num[i]);
        for(int i=1; i<=n; i++)
        {
            r[num[i]] = i;
            if(l.count(num[i]) == 0) l[num[i]] = i;
        }
        while(m--)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            if(l[x] && l[x] < r[y]) printf("YES\n");
            else printf("NO\n");
        }
    }
    
    return 0;
}

D. Not a Cheap String

贪心

从价值最大的往价值最低的开始减

#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;
pii num[maxn];
int vis[maxn];

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        string s;
        int p, sum = 0;
        cin >> s >> p;
        for(int i=0; i<s.length(); i++)
        {
            vis[i] = 0;
            num[i] = {s[i] - 'a' + 1, i};
            sum += s[i] - 'a' + 1;
        }
        sort(num, num + s.length());
        for(int i=s.length() - 1; sum>p && i>=0; i--)
        {
            sum -= num[i].first;
            vis[num[i].second] = 1;
        }
        for(int i=0; i<s.length(); i++)
            if(vis[i] == 0) cout << s[i];
        cout << "\n";
    }
    
    return 0;
}

E. Split Into Two Sets

着色 或 并查集

首先能观察出一些普遍的性质:

  1. 所有数字出现的次数一定是 2 次

  2. 一个骨牌不能有两个相同的数字

我的代码是着色的方法做的:

假设一个骨牌是在 1 号堆,则与其冲突的(拥有相同数字)骨牌一定是在 2 号堆,模拟一次看看有没有冲突即可

并查集:

显然拥有相同数字的骨牌是可以相互连接的,我们要做的就是将每一堆相互连接的骨牌按数字平均分成两半,因此,如果同一堆里骨牌的数量为奇数,则不能平均分成两半

因此并查集就要做到每一堆里的数量都是偶数的

#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 vis[maxn], num[maxn][2], cnt[maxn];
vector<int>gra[maxn];

bool dfs(int now, int col)
{
    if(vis[now]) return vis[now] == col;
    vis[now] = col;
    bool f = true;
    for(int i=0; f && i<gra[num[now][0]].size(); i++)
    {
        int nex = gra[num[now][0]][i];
        if(nex != now)
            f = dfs(nex, col ^ 1 ^ 2);
    }
    for(int i=0; f && i<gra[num[now][1]].size(); i++)
    {
        int nex = gra[num[now][1]][i];
        if(nex != now)
            f = dfs(nex, col ^ 1 ^ 2);
    }
    return f;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        for(int i=0; i<=n; i++) {vis[i] = cnt[i] = 0; gra[i].clear();}
        int f = 1;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<2; j++)
            {
                scanf("%d", &num[i][j]);
                gra[num[i][j]].push_back(i);
            }
            if(num[i][0] == num[i][1]) f = 0;
        }
        for(int i=1; i<=n; i++) if(gra[i].size() != 2) f = 0;
        for(int i=0; i<n && f; i++)
        {
            if(vis[i] == 0) f = dfs(i, 1);
        }
        if(f) printf("YES\n");
        else printf("NO\n");
    }
    
    return 0;
}

F. Equate Multisets

有两个操作,直接搜索也显然不现实,考虑能否将两个操作转换成为一个

如果向下整除没有发生取整的情况,那么乘法和除法为可逆,因此考虑将 \(a\) 数组中所有的数字向下除,直到变成奇数,只要 \(b\) 能够转化为这个奇数,则说明他可以变成相对应的 \(a\)

向上乘肯定没办法变成奇数,因此我们考虑将所有的 b 向下除,直到碰到一个 \(a_i\) 转化成的奇数为止

赛中我用了排序,后来发现并不需要,如果 \(b_i\) 和 \(b_j\) 都能到达某奇数,那么肯定可以沿着相同的路线继续往下除,因此就没有说谁一定要先到

#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 maxm = 2e6 + 10;
const ll inf = 1e17 + 10;
map<int, int>mp;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        mp.clear();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            while((x & 1) == 0)
                x >>= 1;
            mp[x]++;
        }
        int ans = 0;
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            while(x)
            {
                if((x & 1) && mp[x] > 0)
                {
                    mp[x]--;
                    ans++;
                    break;
                }
                x >>= 1;
            }
        }
        if(ans == n) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

G. Passable Paths

LCA

在树上找到形容一条链,只用找到链的两个端点即可,因此这题的初始想法就是找端点

第一个端点:深度最深的地方

第二个端点:离第一个端点最远的那个点

找到两个端点之后,就判断一下其他点是否在这个链上:最快的方法就是判断两个端点到这个点 \(p\) 的距离之和,是不是和链长相等

以上倍增 LCA 实现一下就好了,距离的话直接找到根的距离,也就是深度差,容斥一下算距离就好了

#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;
vector<int>gra[maxn];
int dep[maxn], fa[maxn][25], pa[maxn];

void dfs(int now, int pre, int d)
{
    dep[now] = d;
    fa[now][0] = pre;
    for(auto nex : gra[now])
    {
        if(nex == pre) continue;
        dfs(nex, now, d + 1);
    }

}

void init(int n, int rt = 1)
{
    dfs(rt, rt, 0);
    for(int i=1; i<=20; i++)
        for(int j=1; j<=n; j++)
            fa[j][i] = fa[fa[j][i-1]][i-1];
}

int LCA(int a, int b)
{
    if(dep[a] < dep[b]) swap(a, b);
    int dif = dep[a] - dep[b];
    for(int i=20; i>=0; i--)
    {
        if(dif >= (1 << i))
        {
            dif -= 1 << i;
            a = fa[a][i];
        }
    }
    if(a == b) return a;
    for(int i=20; i>=0; i--)
    {
        if(fa[a][i] != fa[b][i])
        {
            a = fa[a][i];
            b = fa[b][i];
        }
    }
    return fa[a][0];
}

int dis(int a, int b)
{
    return dep[a] + dep[b] - 2 * dep[LCA(a, b)];
}

int main()
{
    int n;
    scanf("%d", &n);
    for(int i=1; i<n; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        gra[x].push_back(y);
        gra[y].push_back(x);
    }
    init(n);
    int m;
    scanf("%d", &m);
    while(m--)
    {
        int k;
        scanf("%d", &k);
        int d = -1, a = 0, b = 0, f = 1;
        for(int i=0; i<k; i++)
        {
            scanf("%d", &pa[i]);
            if(dep[pa[i]] > d) {a = pa[i]; d = dep[pa[i]];}
        }
        d = -1;
        for(int i=0; i<k; i++)
        {
            int x = dis(a, pa[i]);
            if(d < x)
            {
                b = pa[i];
                d = x;
            }
        }
        for(int i=0; i<k && f; i++)
        {
            if(dis(a, pa[i]) + dis(b, pa[i]) != d)
                f = 0;
        }
        printf("%s\n", f ? "yes" : "no");
        
    }
    return 0;
}

标签:10,const,int,ll,Codeforces,maxn,Div,include,805
来源: https://www.cnblogs.com/dgsvygd/p/16475347.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有