A:
题意:给定一个长度为N的整数数组,在数组选择一个数,将这个数转变为一个字母,再给定一个字符串,问这个数组能否转化为这个字符串。
方法:因为每次会将数组中相同的数转化为同一个字母,那么用map记录一下每个数字对应字母,最后再判断对应的位置,字母是否相同,相同则为YES,否则为NO。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
map<int,int>mp;
int a[N];
inline void solve(){
int n;cin>>n;mp.clear();
for(int i=1;i<=n;i++) cin>>a[i];
char s[N];cin>>s+1;
for(int i=1;i<=n;i++)//记录
if(!mp[a[i]]) mp[a[i]]=s[i];
for(int i=1;i<=n;i++)//对比
if(mp[a[i]]!=s[i]){
cout<<"NO\n";return;
}
cout<<"YES\n";
}
int main(){
int T;cin>>T;
while(T--) solve();
}
B:
题意:给定一个长度为N的数组,输入op跟x,有两种操作,如果op=0,则是数组中的每个偶数都会加上x,如果op=1,则是数组中的每个奇数都会加上x。问,每次操作后,输出这个数组的sum
方法:这里如果我们遍历数组再更改数组,再用最后更改的数组求值,那么一定会TLE。所以,这里我们考虑记录原始数组中偶数和奇数的个数,因为每次操作,只会在偶数或者奇数上操作且加的x值都是一样的。(注意:这里加完过后,需要考虑奇偶个数的变化,以进行下一次的操作)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
map<int,int>mp;
int a[N];
inline void solve(){
ll n,q;cin>>n>>q;
ll sum=0,even=0,odd=0;
for(int i=1;i<=n;i++) {
cin>>a[i];sum+=a[i];
if(a[i]%2==0) even++;//偶数个数
else odd++;//奇数个数
}
while(q--){
int op,y;
cin>>op>>y;
if(op==0){
sum+=even*y;//求更改后的sum
if(y%2==1) odd+=even,even=0;//判断奇数偶数个数的变化
}
else{//同上
sum+=odd*y;
if(y%2==1) even+=odd,odd=0;
}
cout<<sum<<"\n";
}
}
int main(){
int T;cin>>T;
while(T--) solve();
}
C:
题意:给定红绿灯的循环节,以及你初始看到的灯,求下一个绿灯等待的最长时间
方法:因为是循环节,所以将字符串的再复制一遍使其长度变为2n,再依次找最长时间。
(这题其实我也不明白为什么要找g跟r相差的最大值。)也许是这一句话吧?
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
inline void solve(){
int n;char c;string s;
cin >> n >> c;
cin >> s;
s = "#" + s + s;
int ans = 0, last = 0;
for(int i = 2 * n; i >= 1 ; i -- ) {
if(s[i] == 'g') last = i;
if(s[i] == c) ans = max(ans, last - i);
}
cout << ans << endl;
}
int main(){
int T;cin>>T;
while(T--) solve();
}
D:
题意:给定一个数组,要求进行若干次操作,使得a[i]乘i上的数,每个数都能最多被乘一次,求最少的操作次数使得数组的乘积能够被2^n整除。
方法:补因子2
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
inline void solve(){
int n,cnt=0;
cin>>n;
vector<int>e;
for(int i=1;i<=n;i++){
int x;cin>>x;
while(x%2==0) x/=2,cnt++;//记录数组中因子2的个数
int dx=0,idx=i;
while(idx%2==0) idx/=2,dx++;//记录下标因子2的个数
if(dx) e.push_back(dx);//将每个下标能分解因子2的个数存入vector
}
if(cnt>=n){//如果数组本身含有的因子2的个数大于等于N,则不用操作
cout<<"0\n";return;
}
int res=n-cnt;//所需要补因子2的个数
sort(e.begin(),e.end(),greater<int>());//降序排列
int pos=0,ans=0;
while(res>0 and pos<e.size()){//进行补因子2
res-=e[pos++];ans++;
}
if(res>0) cout<<"-1\n";//补不完
else cout<<ans<<"\n";//补完
}
int main(){
int T;cin>>T;
while(T--) solve();
}