Codeforces Round 1000 (Div. 2) A-C

链接:Codeforces Round 1000 (Div. 2)

A:Minimal Coprime

大意:

给定一个区间,定义最小互质区间是边界互质,边界内无互质区间。求这个区间最小互质区间个数

思路:

gcd(l, l + 1) = gcd(1, l) = 1,即相邻数组成的区间互质,那么一段区间的互质区间数就为R-L,

还有个一般情况,就是gcd(1,1) = 1,即1自己单独有个最小互质区间

所以对于左边界为1的情况,如果右边界为1结果就是1,右边界大于1为r,那么结果为r - 1,因为虽然[1, 1]属于,但是[1, 2]却因包含[1, 1]而不属于了

代码:

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



void solve() 
{
    int n, m;cin >> n >> m;
    if (n == m && n == 1)cout << 1 << endl;
    else cout << m - n << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

B:Subsequence Update

大意:

给定一个数组的一段区间,可以进行且仅进行一次操作

操作为:选择一个子序列(subsequence, 任意删除原数组中的数构成的序列),然后将该序列中的数反转,比如选取[1 2 3 4 5]。中的 1 3 5, 那么结果为[5 2 3 4 1]

目标为使得区间和最大

思路:

首先对于这个操作,我们目的是使得区间和最大,那就要将区间内较小的数换成区间,

限制是只能进行一次操作,那就不能直接求整个数组最小值和了

先将区间分成三段,区间内区间左边区间右边,

首先我们发现一个性质就是只能区间中间与其中一边进行操作,要不然选取的数左边会和右边抵消掉,使得最后还是只交换一边的效果

那么就分别将左边小数、右边小数与中间大数对调结果取最小即可。

代码:

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



void solve() 
{
    int n;cin >> n;
    int l, r;cin >> l >> r;
    vi a(n + 1);
    for (int i = 1; i <= n; i++)cin >> a[i];
    
    vi ll, rr, mid;
    for (int i = 1; i < l; i++)ll.push_back(a[i]);
    for (int i = l; i <= r; i++)mid.push_back(a[i]);
    for (int i = r + 1; i <= n; i++)rr.push_back(a[i]);
    sort(ll.begin(), ll.end());
    sort(rr.begin(), rr.end());
    sort(mid.begin(), mid.end(), greater<int>());
    int num = 0;
    for (int i = 0; i < mid.size(); i++)num += mid[i];


    int tmp = 0;
    for (int i = 0; i < ll.size() && i < mid.size(); i++)
        if (ll[i] <= mid[i])tmp += mid[i] - ll[i];
        else break;

    int ans = tmp;
    tmp = 0;
    for (int i = 0; i < rr.size() && i < mid.size(); i++)
        if (rr[i] <= mid[i])tmp += mid[i] - rr[i];
        else break;
    ans = max(ans, tmp);
    cout << num - ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/

C:Remove Exactly Two

大意:

给定一个最小生成数,求删除两个点形成的连通分量的最大数量

思路:

首先对于两个点的树,删完点就没点了,结果为1

对于大于两个点的树,我们当然是找度数最大的点去删除,如果两点不相连,那么结果为两点度数相加 - 1, 如果相连,那么两点都去掉后相连的地方就没有连通分量了,结果为两点度数相加 - 2.

那么我的思路是第一个度数最大的点跟其他点删除和度数第二大的点跟其他点删除,结果取最大即可。这样可以排除一些问题,比如前三个点度数是相同的,但是第一个点连着后面两个点,那么第三个点就一定不会连着第二个点,因为要连着就成环了。

代码:

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 998244353;
#define pb push_back
#define  vi vector<int>
#define  vvi vector<vector<int>>
#define  vii vector<pair<int, int>>
#define ff first 
#define ss second 
// ++   ~!    */+-    <<>>    <>  ==   &^|   &&|| =



void solve() 
{

    int n;
    cin >> n;
    map<PII, bool>mp;
    vi cnt(n + 1, 0);
    for (int i = 1; i < n; i++)
    {
        int a, b;cin >> a >> b;
        cnt[a] ++;
        cnt[b] ++;
        mp[{a, b}] = true;
        mp[{b, a}] = true;
    }
    if (n == 2)
    {
        cout << 0 << endl;
        return;
    }

    vii scnt;
    for (int i = 1; i <= n; i++)
        scnt.push_back({ cnt[i], i });
    sort(scnt.begin(), scnt.end(), greater<PII>());
    

    int ans = 0;
    for (int i = 1; i < n; i++)
        ans = max(ans, scnt[0].ff + scnt[i].ff - 1 - mp[{scnt[0].ss, scnt[i].ss}]);

    for(int i = 2; i < n; i ++)
        ans = max(ans, scnt[1].ff + scnt[i].ff - 1 - mp[{scnt[1].ss, scnt[i].ss}]);
    
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--) solve();

    return 0;
}
/*   /\_/\
*   (= ._.)
*   / >  \>
*/
相关推荐
SharkWeek.2 分钟前
【力扣Hot 100】普通数组2
数据结构·算法·leetcode
敲上瘾3 分钟前
动静态库的制作与使用(Linux操作系统)
linux·运维·服务器·c++·系统架构·库文件·动静态库
Uitwaaien545 分钟前
51单片机——按键控制LED流水灯
c++·单片机·嵌入式硬件·51单片机
漫漫进阶路4 小时前
VS C++ 配置OPENCV环境
开发语言·c++·opencv
XianxinMao7 小时前
RLHF技术应用探析:从安全任务到高阶能力提升
人工智能·python·算法
hefaxiang7 小时前
【C++】函数重载
开发语言·c++·算法
花生树什么树8 小时前
下载Visual Studio Community 2019
c++·visual studio·vs2019·community
练小杰8 小时前
Linux系统 C/C++编程基础——基于Qt的图形用户界面编程
linux·c语言·c++·经验分享·qt·学习·编辑器
勤又氪猿8 小时前
【问题】Qt c++ 界面 lineEdit、comboBox、tableWidget.... SIGSEGV错误
开发语言·c++·qt