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;
}