Codeforces 2025/6/8

E. Three Strings

题目大意:给你3个字符串a,b,c,每次取a或b的首字符添加到新字符的末尾,让你求出c与新字符最少有多少个字符不同

思路:经典的字符串匹配的动态规划题,f[i][j]表示a的前i个字符和b的前j个字符中与c的前(i+j)个字符最大匹配数,转移方程:f[i+1][j] = max(f[i][j]+(a[i] == c[i+j]) ), f[i][j+1] = max(f[i][j] + (b[j] == c[i+j]) f[0][0] = 0, 注意边界

代码:

void solve()

{

    string a,b,c;

    cin >> a >> b >> c;

    int n = a.size(), m = b.size();

    vector<vector<int>> f(n+1,vector<int>(m+1,-1e9));

    f[0][0] = 0;

    for (int i = 0; i <= n; i ++ )

        for (int j = 0; j <= m; j ++ )

        {

            if (i + 1 <= n) f[i+1][j] = max(f[i+1][j],f[i][j] + (a[i] == c[i+j]));

            if (j + 1 <= m) f[i][j+1] = max(f[i][j+1],f[i][j] + (b[j] == c[i+j]));

        }

    cout<<n+m-f[n][m]<<endl;

}

链接:Problem - 2050E - Codeforces

E. Sakurako, Kosuke, and the Permutation

题目大意:给你一个排列,问你操作几次元素交换,能将这个排列变为简单排列,简单排列的定义为

如果每个 ii (1≤i≤n)(1≤i≤n) 中都有一个,那么排列 pp 就被认为是简单的。 (1≤i≤n)(1≤i≤n) 都成立,那么这个排列 pp 就是简单排列:

  • pi=ipi=i
  • ppi=i

思路:找环,每次把环中元素数减1除2加到答案上去

代码:

void solve()

{

    int n; cin >> n;

    vector<int> p(n+1),st(n+1);

    for (int i = 1; i <= n; i ++ ) cin >> p[i];

    int ans = 0;

    for (int i = 1; i <= n; i ++ )

    {

        st[i] = 1;

        int cnt = 1, x = i;

        while (!st[p[x]] && p[x] != x)

        {

            cnt ++ ;

            st[p[x]] = 1;

            x = p[x];

        }

        ans += (cnt - 1)/2;

    }

    cout<<ans<<endl;

}

链接:Problem - 2033E - Codeforces

C. Two Movies

题目大意:有两个数组,你每次可以从这两个数组中任取一个数加到该数组对应的和中,最后叫你求最大的(这两个和中的较小的那一个)

#1 因为元素中只有0,-1,1,所以当这两个数组在某点时不相等时,取较大的那个就行

#2 相等的情况则要令判

思路:我们可以离线操作,先不算相等的情况,把相等的情况记录下来,最后根据两个合来判断取拿个,当都为-1时,合较大的那个取,为1时,合较小的那个取

代码:

void solve()

{

    int n; cin >> n;

    vector<array<int,2>> v(n);

    int ans1 = 0, ans2 = 0;

    for (int i = 0; i < n; i ++ ) cin >> v[i][0];

    for (int i = 0; i < n; i ++ ) cin >> v[i][1];

    vector<int> op;

    for (int i = 0; i < n; i ++ )

    {

        if (v[i][0] > v[i][1]) ans1 += v[i][0];

        else if (v[i][0] < v[i][1]) ans2 += v[i][1];

        else op.push_back(v[i][0]);

    }

    for (auto t : op)

    {

        if (t == 1)

        {

            if (ans1 >= ans2) ans2 ++ ;

            else ans1 ++ ;

        }

        else if (t == -1)

        {

            if (ans1 >= ans2) ans1 -- ;

            else ans2 -- ;

        }

    }

    cout<<min(ans1,ans2)<<endl;

}

链接:Problem - 1989C - Codeforces

C. Set Construction

题目大意:给你一个二进制方阵,让你根据该位置0,1的情况来构造n个不同的集合

#1 思考如何构造

思路:先给每个排列设置一个不同的初始值,如果i包含于j,就将i的初始值放进j中,对于a包含于b,a包含于c,b包含于c的情况,是否应该将b的改变值放进c呢,不需要,因为b包含于c时,必有a也包含于c

代码:

void solve()

{

    int n; cin >> n;

    vector<string> g(n+1);

    for (int i = 1; i <= n; i ++ )

    {

        cin >> g[i];

        g[i] = ' ' + g[i];

    }

    set<int> s[n+1];

    for (int i = 1; i <= n; i ++ )

        s[i].insert(i);

    for (int i = 1; i <= n; i ++ )

        for (int j = 1; j <= n; j ++ )

        {

            if (g[i][j] == '1') s[j].insert(i);

        }

    for (int i = 1; i <= n; i ++ )

    {

        cout<<s[i].size()<<" ";

        for (auto it = s[i].begin(); it != s[i].end(); it++)

            cout<<*it<<" ";

        cout<<endl;

    }

}

链接:Problem - 1761C - Codeforces

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值