ICode9

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

AtCoder Beginner Contest 236 (C-E)

2022-01-25 22:02:55  阅读:145  来源: 互联网

标签:AtCoder cnt Beginner int res mid st 236 include


C - Route Map

题意:给定n个S串和m个T串,对于每一个S串问是否其出现在T串中。

题解:map模拟记录T串,对于S,询问map中是否存在就行。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <vector>
#include <map>

using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
string s[N];
map<string, bool> h;

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
        cin >> s[i];
    
    string res;
    for (int i = 1; i <= m; i ++ )
    {
        cin >> res;
        h[res] = true;
    }
    for (int i = 1; i <= n; i ++ )
        if (h[s[i]]) puts("Yes");
        else puts("No");
    return 0;
}

D - Dance (dfs)

题意:有n个人,并给出两两配对的亲和度,找出所有匹配对的亲和度的异或最大值

题解:对于每个人,去寻找还未匹配到人的就行,第一个人可匹配的人数为(n - 1),第二个未匹配的人可匹配的人数为(n - 3),依次类推,因此复杂度为O((n - 1) (n - 3) * (n - 5)…*2),n最大是16,因此时间复杂度试2e6左右。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
const int N = 30;
int g[N][N];  // g[i][j]表示i和j匹配的亲和度
bool st[N];   // 用于标记此人是否匹配了
int ans = 0, n;


// cnt表示这是第几个人,res是当前及匹配的亲和度的异或值
void dfs(int cnt, int res)
{
    if (!cnt)    // 匹配完
    {
        ans = max(ans, res);
        return;
    }
    if (st[cnt])  // 这个人已经被匹配了
    {
        dfs(cnt - 1, res);
        return;
    }
    for (int i = 1; i <= n; i ++ )
    {
        if (i == cnt || st[i]) continue;
        st[cnt] = st[i] = true;
        dfs(cnt - 1, res ^ g[cnt][i]);
        st[cnt] = st[i] = false;   // 回溯,还原现场
    }
}

int main()
{    
    scanf("%d", &n);
    n *= 2;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
        {
            if (j <= i) continue;
            scanf("%d", &g[i][j]);
            g[j][i] = g[i][j];
        }
    
    dfs(n, 0);
    printf("%d\n", ans);
    return 0;
}

E - Average and Median (二分 + DP)

题意:给出n 个数a1…an,然后选取一些数出来,选取数的方式是对于每一个 i (1<=i<=n-1), 第i个数或第i+1个数至少选出来一个,问在所有的这些选法中的最大平均值和最大中位数是多少。

题解:二分答案用dp去check二分出来的值是否合法。

对于求最大的平均值:假设现在二分到的答案是mid,那么我们令b[i] = a[i] - mid,如果按题目给出的选法在b数组中选出的数的和至少有一组大于等于0说明真实答案一定不会比mid小,然后令l = mid, 所以我们只需求出最大的一组和就行。令f[i][0]表示从前i个数里面选且不选i的最大的和,f[i][1]表示从前i个数里面选且选i的最大的和,因此f[i][0] = f[i - 1][1](第i个不选,因此第i - 1个一定要选),f[i][1] = max(f[i - 1][0], f[i - 1][1]) + b[i](第i个选,因此第i - 1个可选可不选,找其中的最大值就行),若max(f[i][0], f[i][1]) >= 0, 说明选出来的方案中至少存在一组数的和大于等于0.

对于求最大的中位数:对于中位数我们可以发现大于等于中位数的数的数量一定是 大于 小于中位数的数的数量(有点拗口 ),所以只要我们能在a[i]中按题目的选法选出大于等于mid的数量 大于 小于mid的数量,说明真实答案一定不会比mid小,然后令l = mid。因此在这里, 如果a[i] >= mid,则令b[i] = 1, 否则令b[i] = -1,所以在b数组中选出一组数的和大于0即可,我们同样是找选出来的和最大值是否大于0即可,dp转移方程如上。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int g[N];
int n;

bool check1(double x)
{
    vector<vector<double> > f(n + 1, vector<double>(2));
    f[0][0] = 0, f[0][1] = 0;
    for (int i = 1; i <= n; i ++ )
    {
        f[i][0] = f[i - 1][1];
        f[i][1] = max(f[i - 1][1], f[i - 1][0]) + g[i] - x;
    }
    // cout << x << " " << max(f[n][0], f[n][1]) << endl;
    return max(f[n][0], f[n][1]) >= 0;
}

bool check2(int x)
{
    vector<vector<int> > f(n + 1, vector<int>(2));

    for (int i = 1; i <= n; i ++ )
    {
        f[i][0] = f[i - 1][1];
        f[i][1] = max(f[i - 1][1], f[i - 1][0]) + (g[i] >= x ? 1 : -1);
    }
    return max(f[n][0], f[n][1]) > 0;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &g[i]);

    double l = 0, r = 1e9;
    while (r - l >= 1e-6)
    {
        double mid = (l + r) / 2;
        if (check1(mid)) l = mid;
        else r = mid;
    }
    
    int L = 0, R = 1e9;
    while (L < R)
    {
        int mid = L + R + 1 >> 1;
        if (check2(mid)) L = mid;
        else R = mid - 1;
    }
    cout << l << "\n" << L << endl;
    return 0;
}

完结,如有错误,还请指出,感谢!!!

标签:AtCoder,cnt,Beginner,int,res,mid,st,236,include
来源: https://blog.csdn.net/m0_53430148/article/details/122692611

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

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

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

ICode9版权所有