A:
题意:给定三个数字,问是否能够构成两个数之和等于另一个数。
方法:将三个数字排序,判断前两个数相加是否等于最后一个数
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int a[N];
int main(){
cin>>t;
while(t--){
memset(a,0,sizeof(a));
for(int i=1;i<=3;i++) cin>>a[i];
sort(a+1,a+4);
if(a[1]+a[2]==a[3]) cout<<"YES\n";
else cout<<"NO\n";
}
}
B:
题意:给一个长度为N的数组,判断是否能构成严格单调递增的数组。
方法:如果数组中的每个数仅出现一次,那么一定可以构成,否则不能。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,a[N];
set<int>e;//set容器自动消除重复的元素
int main(){
cin>>t;
while(t--){
cin>>n;e.clear();
for(int i=1;i<=n;i++){
cin>>a[i];e.insert(a[i]);
}
if(e.size()==n) cout<<"YES\n";//如果容器里面的大小等于数组大小,则说明数各不相等
else cout<<"NO\n";
}
}
C:
题意:给一个8x8的板子,经过别人涂色过后(只有两种颜色,R、B),(注意:每次图色,只能是涂一行或者涂一列相同的颜色),求最后一次涂的颜色是什么颜色?
方法:因为经过多次涂色过后,肯定会有颜色覆盖,那么我们从行的角度来考虑,如果某一行全是R(B),那么最终的颜色就是R(B)。
代码:
#include <bits/stdc++.h>
using namespace std;
string s;
void solve(){
bool ok = false;
for(int i = 1; i <= 8; i++){
cin >> s;
if(s == "RRRRRRRR") ok = true;
}
if(ok) cout<<"R\n";
else cout<<"B\n";
}
int main(){
int T;cin >> T;
while(T--) solve();
}
D:
题意:给定一个长度为N且不可改动的数组,若能求出数组中两个数a[i]=A,a[j]=B,A与B互为质数且i+j是最大,输出max(i+j),否则输出-1。
方法:因为N<=10000,所以可以用枚举。记录数组中每个数的下标,再依次枚举答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4;
int idx[N];//idx数组用于记录下标
void solve(){
int n;cin>>n;memset(idx,0,sizeof(idx));
for(int i=1;i<=n;i++){
int x;cin>>x;
idx[x]=i;
}
int ans=-1;
for(int A=1;A<=10000;A++)
for(int B=1;B<=10000;B++)
if(idx[A]>0&&idx[B]>0&&__gcd(A,B)==1) //如果A和B对应的下标存在,且A和B互为质数
ans=max(ans,idx[A]+idx[B]);
cout<<ans<<"\n";
}
int main(){
int T;cin>>T;
while(T--){
solve();
}
}
E:
题意:给了N阶楼梯,每一阶的高度为ai,进行Q次询问,每次询问给定一个高度H,如果H>ai,则可以爬上这阶楼梯,否则就不能爬上这阶楼梯。 求能爬多高?
前置知识:upper_bound(二分)
链接:https://blog.csdn.net/qq_40160605/article/details/80150252
方法:因为upper_bound是从数组中最小的元素到最大的元素依次查找,所以我们需要用一个数组来维护阶梯的高度,再用sum数组维护前缀和,最后输出值。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int a[N],b[N],sum[N];
void solve(){
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=max(b[i-1],a[i]);//用b数组维护前个最大值
sum[i]=sum[i-1]+a[i];//sum数组维护前缀和
}
//cout<<"b[]:";
//for(int i=1;i<=n;i++) cout<<b[i]<<" ";
//cout<<"sum[]";
//for(int i=1;i<=n;i++) cout<<sum[i]<<" ";
while(q--){
int x;cin>>x;
int t=upper_bound(b+1,b+1+n,x)-b-1;//第一个大于x的位置:upper_bound(b+1,b+1+n,x)-b
//cout<<"t:"<<t<<" ";
//cout<<"ans="<<sum[t]<<" "<<endl;
cout<<sum[t]<<" ";
}
puts("");
}
signed main(){
int T;cin>>T;
while(T--){
solve();
}
}
F:
题意:给两个字符串,并初始都是"a",进行选择操作,op=1是在第一个字符串后面加k个字符串,op=2是在第二个字符串后面加k个字符串。(拼接的字符串是可以改变字母位置的),问能否满足拼接后的字符串a<b,能则输出YES,否则初始NO。
方法:因为拼接字符串的过程中,字母位置可以改变,如果想使第一个字符串<第二个字符串的,那么就尽可能的将不是字母‘a’的字母放在前面,才能尽可能使第二个字符串>第一个字符串
这里举样例1:
得出的贪心策略:如果在添加字符串时,出现了非'a'的字母,如果是op=1,则是NO,如果是op=2,则是YES。如果拼接后,两个字符串相等,则比较长度。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
char s[N];
int main(){
int T;cin>>T;;
while(T--){
int n;cin>>n;
ll c1=1,c2=1,p1=0,p2=0;
//c1、c2分别统计字符串1和2中字母‘a’的个数,p1表示字符串1中有非'a'字母,p2同理
while(n--){
int op,k;
scanf("%d%d%s",&op,&k,s+1);
if(op==1)
for(int i=1;s[i];i++){
if(s[i]=='a') c1+=k;
else p1=1;
}
else
for(int i=1;s[i];i++){
if(s[i]=='a') c2+=k;
else p2=1;
}
//如果p2出现了非'a'字母,或者字符串相等,c1<c2
if(p2||c1<c2&&p1==0) cout<<"YES\n";
else cout<<"NO\n";
}
}
}
G:
题意:给定一个长度为N的数组a,输出一个同等长度的数组b。b数组满足
方法:暴力枚举。
要使b数组的字典序最大,就是每个前缀或都是最大的,所以我们直接求前缀或每个部分的最大值即可。采用两次遍历,每次都求出对应的前缀或最大值。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int a[N];
inline void solve(){
int n;cin>>n;int idx;
for(int i=1;i<=n;i++) cin>>a[i];
int cur=0;//上一个部分最大的前缀或
for(int i=1;i<=n;i++){
int mx=0;//记录最大前缀或
for(int j=i;j<=n;j++){//从上一次前缀或的最后一个元素开始找最大前缀或
if((a[j]|cur)>mx){
mx=(a[j]|cur);
idx=j;
}
}
swap(a[i],a[idx]);//更换位置,使得前缀或最大
if(cur!=mx) cur=mx;//如果上一部分的最大前缀或不是最大的,则更新最大的
else break;
//如果上一次最大前缀或是等于下一次最大前缀或的,则说明后面的元素值已经没有贡献了
}
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<"\n";
}
int main(){
int T;cin>>T;
while(T--) solve();
}