2022.4.15

AtCoder Beginner Contest 236

A - chukodai

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    string s;
    cin >> s;
    int a, b;
    cin >> a >> b;
    swap(s[a - 1], s[b - 1]);
    cout << s;

    return 0;
}

B - Who is missing?

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int vis[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= 4 * n - 1;i++)
    {
        int x;
        cin >> x;
        vis[x]++;
    }
    for (int i = 1; i <= n;i++)
    {
        if(vis[i]==3)
        {
            cout << i << '\n';
            break;
        }
    }
        return 0;
}

C - Route Map

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<string,int> psi;
const int N=1e5+10,INF=1e9;
psi a[N];
map<string, int> mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin >> n >> m;
    for (int i = 1; i <= n;i++)
    {
        cin >> a[i].first;
        a[i].second = 0;
    }
    for (int i = 1;i<=m;i++)
    {
        string s;
        cin >> s;
        mp[s] = 1;
    }
    for (int i = 1; i <= n;i++)
    {
        if(mp[a[i].first])
        {
            cout << "Yes\n";
        }
        else
            cout << "No\n";
    }
        return 0;
}

D - Dance

两两配对选择舞伴,以为dfs会超时实际上是不会的,需要注意当一对舞伴被选了后,后面的就不能再重复选其中的任意一个了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=15+10,INF=1e9;
int a[N][N],ans,n;
bool vis[N];
void dfs(int now,int res)
{
    if(now==0)
    {
        ans = max(res, ans);
        return;
    }
    if(vis[now])
    {
        dfs(now - 1, res);
        return;
    }

    for (int i = 1; i <= n ;i++)
    {
        if(!vis[i]&&i!=now)//当前的层数和选的数都没有没选过
        {
            vis[i] = 1;
            vis[now] = 1;
            dfs(now - 1, res ^ a[now][i]);
            vis[i] = 0;//还原现场
            vis[now] = 0;
        }
    }
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    n = n * 2;
    for (int i = 1; i < n;i++)
    {
        for (int j = i+1; j <= n;j++)
        {
            cin >> a[i][j];
            a[j][i] = a[i][j];
        }
    }
    dfs(n-1, 0);
    cout << ans;
    return 0;
}

E - Average and Median

有一点像力扣的打家劫舍问题,需要连续的数至少要选到一个,分别求出最大的平均值和中位数。此题可以用二分的思想来做,令l=1,r=1e9,枚举mid(即均值),一想到平均值可以先将原数组的所有数都先减去平均值最后如果和大于等于平均值的话说明成功,于是令l=mid。考虑每个数有选和不选两种状态,当不选这个数,那么它前面的数必须要选,否则不满足题目的要求,如果选择这个数,那么前一个数可选可不选,我们只需要保存二者的最大值再加上当前的值即可,如果最后的和>=0,说明成功。同理对于中位数而言,我们可以知道数组中大于等于中位数的数一定大于 小于中位数的数。那么我们再次二分mid,即中位数,对于数组的数,如果大于等于中位数我们令其为,否则为-1。再次执行上次的二分操作即可,注意mid必须是大于0的才算成功,因为大于等于中位数的数的个数一定大于 小于中位数的个数,因此如果符合结果一定大于0。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int a[N],c[N],dp2[N][2],n;
double b[N],dp1[N][2];
bool check1(double mid)
{
    for (int i = 1; i <= n;i++)
    {
        b[i] = a[i] - mid;
    }
    for (int i = 1; i <= n;i++)
    {
        dp1[i][0] = dp1[i - 1][1];
        dp1[i][1] = max(dp1[i - 1][1], dp1[i - 1][0]) + b[i];
    }
    double ans = max(dp1[n][1], dp1[n][0]);
    return ans >= 0;
}
bool check2(int mid)
{
    for (int i = 1; i <= n;i++)
    {
        if(a[i]>=mid)
            c[i] = 1;
        else
            c[i] = -1;
    }
    for (int i = 1; i <= n;i++)
    {
        dp2[i][0] = dp2[i - 1][1];
        dp2[i][1] = max(dp2[i - 1][1], dp2[i - 1][0]) + c[i];
    }
    int ans = max(dp2[n][1], dp2[n][0]);
    return ans > 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n;i++)
    {
        cin >> a[i];
    }
    double l = 1, r = 1e9;
    while(r-l>1e-6)
    {
        double mid = (l + r) /2 ;
        if(check1(mid))
        {
            l = mid;
        }
        else
            r = mid;
    }
    printf("%.6f\n", l);

    int nl = 1, nr = 1e9;
    while(nl<nr)
    {
        int mid = nl + nr + 1 >> 1;
        if(check2(mid))
        {
            nl = mid;
        }
        else
            nr = mid - 1;
    }
    printf("%d", nl);
    return 0;
}

F - Spices

根据贪心的策略我们知道肯定是优先选择花费小的,然后再选择符合要求的方案,假定最开始的方案集合为空,遍历pair数组,如果集合内没有这个数或者是不能通过相互异或的方式得到这个数的话,就必须放进集合,否则不能构成从1-2^n-1的所有数,放入集合后同时需要更新集合个数,将新加入的数与集合的数相互异或得到的新数再次放入集合,直至遍历完毕即可得到最小的花费,还有一种线性基的做法,不太了解。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
pii a[(1<<16)+10];
bool vis[(1<<16)+10];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for (int i = 1; i < (1 << n);i++)
    {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a + 1, a + (1<<n));
    ll ans = 0;
    for (int i = 1; i <(1<<n);i++)
    {
        int x = a[i].first;
        int y = a[i].second;
        if(!vis[y])
        {
            vis[y] = 1;
            ans += x;
            for (int j = 1; j < (1 << n);j++)
            {
                if(vis[j])
                {
                    vis[j ^ y] = 1;
                }
            }
        }
    }
    cout << ans;
    return 0;
}
posted @ 2022-04-15 22:48  menitrust  阅读(14)  评论(0编辑  收藏  举报