Codeforces Global Round 15

A Subsequence Permutation

题目大意

给你一个长度为n的字符串,确定一个最小数字k,将k个字符重新排列后字符串有序

主要思路

记录原字符串,记录排序后的字符串,遍历如果有一个字符不相等ans++,输出ans

AC代码
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 200010;
int n, a[N];
char s[N], s1[N];

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 0; i < n; i++)
        {
            cin >> s[i];
            s1[i] = s[i];
        }
        
        sort(s, s + n);
        
        int res = 0;
        for(int i = 0; i < n; i++)
        {
            if(s[i] != s1[i]) res++;
        }
        cout << res << endl;
    }
    return 0;
}

B Running for Gold

题目大意

给你n个运动员,每个运动员有5场比赛排名,当x运动员至少有3场比赛比y运动员排名低时说明x运动员优于y运动员,请找出n个运动员中比其他运动员都优秀的运动员,如果不存在输出-1

主要思路

先从1n遍历找出当前最优秀的运动员,再从1n遍历,假如有比当前运动员更优秀的输出-1

AC代码
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 50010;
int n, a[N][10];

bool check(int x, int y)
{
    int cnt = 0;
    for(int i = 1; i <= 5; i++)
    {
        if(a[x][i] < a[y][i]) cnt++;
    }
    if(cnt >= 3) return true;
    return false;
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= 5; j++)
            {
                cin >> a[i][j];
            }
        }
        
        int res = 1;
        for(int i = 2; i <= n; i++)
        {
            if(check(i, res)) res = i;
        }
        int t = res;
        for(int i = 1; i <= n; i++)
        {
            if(i == res) continue;
            if(check(res, i)) ;
            else t = -1;
        }
        cout << t << endl;
    }
    return 0;
}

C Maximize the Intersections

题目大意

给你一个数n,圆上有顺时针的2 * n个点,给你了n条线段,问剩下的点怎么连使得线段交点最多,每个点只能被用一次。

主要思路

首先考虑两线段之间有交点满足什么条件,(x1, y1) (x2, y2) (x1 < y1, x2 < y2)当两线段相交时,一定满足x1 < x2 < y1 < y2或者x2 < x1 < y2 < y1,那么我们把剩余没被用过的点排序,想办法构成最多的相交序列,于是我们可以将排序后的数组前半段和后半段分开,每次从前半段和后半段按顺序取一个数凑成一条线段,这样构造出来的线段交叉最多,也就是交点最多

AC代码
#include<bits/stdc++.h>

using namespace std;

#define x first
#define y second
typedef long long ll;
const int N = 1010;
int n, k;
pair<int, int> p[N];
bool st[N];
int num[N];

bool check(int a, int b)
{
    if(p[a].x < p[b].x && p[a].y < p[b].y && p[b].x < p[a].y || p[b].x < p[a].x && p[b].y < p[a].y && p[a].x < p[b].y) return true;
    else return false;
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        memset(st, 0, sizeof(st));
        cin >> n >> k;
        for(int i = 0; i < k; i++)
        {
            int a, b;
            cin >> a >> b;
            if(a > b) swap(a, b);
            p[i] = {a, b};
            st[a] = st[b] = true;
        }
        
        int cnt = 0;
        for(int i = 1; i <= 2 * n; i++)
        {
            if(!st[i]) num[cnt++] = i;
        }
        

        for(int i = 0; i < cnt / 2; i++)
        {
            p[k++] = {num[i], num[i + cnt / 2]};
        }
        
        //for(int i = 0; i < n; i++) cout << p[i].x << ' ' << p[i].y << endl;
        
        ll res = 0;
        for(int i = 1; i < n; i++)
        {
            for(int j = 0; j < i; j++)
            {
                if(check(i, j)) res++;
            }
        }
        cout << res << endl;
    }
    return 0;
}

D Array Differentiation

题目大意

给定一个长度为n的a数组,问你能否构造出一个长度为n的数组b,满足b中存在两个数的差为a数组中的元素,且a数组中的元素必须都出现

主要思路

先考虑如何构造数组b,假设b中存在一个数x,根据与a数组的关系,我们必然构造下一个数为x + a[i],那么当我们遍历到a数组的第n - 1位时,b数组已经长度为n,那么如何才能构造出数组b呢,可以想到,如果a中的一个数能被其他数表示出来,也就是a数组中任意个元素能凑出的数中存在重复元素,那么一定能构造出数组b,n的数据范围为10,所以我们用2进制枚举a数组选与不选的所有状态,找到所有可能的值,如果存在重复元素输出YES,否则输出NO

AC代码
#include<bits/stdc++.h>

using namespace std;

#define x first
#define y second
typedef long long ll;
const int N = 500010;
int n, k;
ll a[N];

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
        
        set<int> s;
        for(int i = 0; i < 1 << n; i++)
        {
            int sum = 0;
            for(int j = 0; j < n; j++)
            {
                if((i >> j) & 1) sum += a[j];
            }
            s.insert(sum);
        }
        if(s.size() < 1 << n) puts("YES");
        else puts("NO");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值