A Download More RAM
题意:升级内存,给定初始内存,使用给定的n个软件升级内存,第i个软件启动要求至少a内存,可以永久增加b内存,求最大内存
思路:排序贪心即可
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int N = 100 + 10;
int t,n,k;
struct node
{
int a,b;
}no[N];
bool cmp(node a,node b)
{
if(a.a == b.a) return a.b>b.b;
return a.a < b.a;
}
int main()
{
ios
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i = 0 ; i < n ; i ++ ) cin>>no[i].a;
for(int i = 0 ; i < n ; i ++ ) cin>>no[i].b;
sort(no,no+n,cmp);
ll ans = 0;
for(int i = 0 ; i < n ; i ++ )
{
if(k < no[i].a) break;
k += no[i].b;
}
cout<<k<<"\n";
}
return 0;
}
B - GCD Arrays
题意:给一个区间,问能否在k次操作内,将操作后区间内剩余的所有数的最大公约数大于1
思路:可知偶数和奇数的最大公约数只能是1,所以将奇数消掉,这样最大公约数变为2,所以看区间内的奇数个数是否小于等于k,特判区间长度为1情况
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int N = 100 + 10;
int t,l,r,k;
int main()
{
ios
cin>>t;
while(t--)
{
cin>>l>>r>>k;
int ans = 0;
vector<int> ve;
int len = r - l + 1;
if(l %2 != 0 && len %2 != 0) ans = len / 2 + 1;
else ans = len / 2;
if(k == 0 && l-r == 0)
{
if(l > 1) puts("YES");
else puts("NO");
}
else if(ans <= k) puts("YES");
else puts("NO");
}
return 0;
}
C - Meximum Array
题意:给一个数组a,根据a创建最大的数组b,操作如下:选前k个数,删掉,添加前k个数的mex到b中。
其中,一组非负整数的MEX是不在该集合的非负整数的最小值。例如,
M
E
X
(
1
,
2
,
3
)
=
0
MEX({1,2,3}) =0
MEX(1,2,3)=0 ,
M
E
X
(
0
,
1
,
2
,
4
,
5
)
=
3
MEX({0,1,2,4,5}) =3
MEX(0,1,2,4,5)=3。
输出b的长度和数组。
思路:利用map记录相同的数字剩余个数,将同一组的id标记相同,每次使用添加在b数组中,可以找到,当前now++
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int t,n;
int a[N],b[N];
vector<int> ve;
map<int,int> mp;
int main()
{
ios
cin>>t;
int id = 1;//id记录同一组
while(t--)
{
ve.clear();
mp.clear();
cin>>n;
for(int i = 0 ; i < n ; i ++ ) cin>>a[i],mp[a[i]] ++;
int now = 0;
for(int i = 0 ; i < n ; i ++ )
{
b[a[i]] = id;//标记
mp[a[i]] --;
while(b[now] == id) now ++;//可以找到,now++
if(!mp[now])
{
ve.push_back(now);
id ++;//更换另一组
now = 0;
}
}
cout<<ve.size()<<"\n";
for(auto v:ve)
{
cout<<v<<" ";
}
cout<<"\n";
}
return 0;
}
D - Peculiar Movie Preferences
题意:给n个字符串,长度不超过3,删掉任意个后,问剩余的字符串顺序连接是否为回文串
思路:经过思考后,可以生成回文串的只有以下几种情况
- 只有长度为1或者全部由1种字母组成
- 长度为2,找完全相反的无需看顺序,或者和前面出现的长度为3的组合,例如abc和ba
- 长度为3,找完全相反的无需看顺序,或者和前面出现的长度为2的组合,例如ab和cba
所以开两个map来记录,一个记录原字符串数组,一个记录前面出现的长度为3的部分字母,便于第二种情况判断
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int t,n;
string s[N];
map<string,int> mp,mp1;
int main()
{
ios
cin>>t;
while(t--)
{
mp.clear();
mp1.clear();//存放前面已经出现的,需要符合顺序关系
cin>>n;
bool flag = false;
for(int i = 0 ; i < n ; i ++ ) cin>>s[i];
for(int i = 0 ; i < n ; i ++ )
{
mp[s[i]] ++;
if(s[i].size() == 1)
{
flag = true;
break;
}
else if(s[i].size() == 2 && s[i][0] == s[i][1])
{
flag = true;
break;
}
else if(s[i].size() == 3 && s[i][0] == s[i][1] && s[i][0] == s[i][2])
{
flag = true;
break;
}
else if(s[i].size() == 2)
{
string s1 = "";
s1 += s[i][1] , s1 += s[i][0];
if(mp[s1] || mp1[s1])
{
flag = true;
break;
}
}
else if(s[i].size() == 3)
{
string s1 = "";
s1 += s[i][2] , s1 += s[i][1] , s1 += s[i][0];//找相反的
string s2 = "";
s2 += s[i][0] , s2 += s[i][1];
mp1[s2] ++;//给后面长度为2的使用
string s3 = "";
s3 += s[i][2] , s3 += s[i][1];//找前面可以匹配的长度为2
if(mp[s1] || mp[s3])
{
flag = true;
break;
}
}
}
if(flag) cout<<"YES";
else cout<<"NO";
cout<<"\n";
}
return 0;
}