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遍历,假如有比当前运动员更优秀的输出-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 secondtypedef 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 secondtypedef 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;}
