A:
题意:给定一个由QA组成的字符串,Q表示问题,A表示回答,要求每一个Q后面都能对应至少一个A。
方法:栈。我们发现,只有一个Q后面有一个A就行,多个A无所谓,那么QQ就需要后面两个A。所以,我们用ans记录Q的个数,在每个Q后面遇见A,就减去一个Q的个数,最后判断还有没有Q,如果没有则说明,合法,否则非法。
代码:
#include<bits/stdc++.h>
using namespace std;
string s;
int n;
inline void solve(){
cin>>n>>s;
int ans=0;
for(int i=0;i<s.size();i++){
if(s[i]=='Q') ans++;
else ans--;
if(ans<0) ans=0;
}
if(ans) cout<<"NO\n";
else cout<<"YES\n";
}
int main(){
int T;cin>>T;
while(T--) solve();
}
B:
题意:给定数组长度n,请构造一个排列使得两个相邻元素差的最小值最大。
方法:因为是构造题。所以我猜的最大值是n/2,但是确实构造的差值就是n/2。如果我们构造(1,n),(2,n-1),最终会发现差值为1,肯定不是最大值。然后再考虑(1,n/2),(2,n/2+1),这样发现确实是可行的。如果n是奇数,我们就把第n个数放在前面即可
代码:
#include<bits/stdc++.h>
using namespace std;
inline void solve(){
int n;cin>>n;
int k=n/2;
for(int i=k;i;i--)
for(int j=i;j<=n;j+=k)
cout<<j<<" ";
cout<<"\n";
}
int main(){
int T;cin>>T;
while(T--) solve();
}
C1:
题意:给一个只包含1和-1的数组,区间[L , R]的价值为a[l] - a[l+1] + a[l+2] ……+(-)a[r]
求一个划分,使得每个区间的价值之和为0 , 不需要最小化划分数
思路:我们发现,当数组长度是奇数的时候,不管怎样划分都不可能成功。当为偶数的时候,我们只需要从左往右两个元素两个元素的看。如果两个元素是一样的,就划分为一组,如果不一样,就各自划分一组。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+10;
int a[N];
inline void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n%2==1){
cout<<"-1\n";return;
}
vector<PII>v;
for(int i=1;i<=n;i+=2){
if(a[i]==a[i+1]) v.push_back({i,i+1});
else{
v.push_back({i,i});
v.push_back({i+1,i+1});
}
}
cout<<v.size()<<"\n";
for(auto i:v){
cout<<i.first<<" "<<i.second<<"\n";
}
}
int main(){
int T;cin>>T;
while(T--) solve();
}
D:
题意:给定一个长度为n的数组和k,判断k!是否整除(a1! + a2! + a3! + a4!... + an!)
方法:首先,这道题是肯定不能暴力的。一开始我以为是找因子,简要的思绪并没有取得满意的结果。后面看了看别人的题解,发现确实很巧妙。分析:
map来统计每一个数出现的次数,我们发现一个数字出现的次数可以累加到这个数的上一位。比如出现了5个4,那么这5个4就可以形成一个5的倍数,相当于多出现了一个5。我们从低位往高位累加,判断mp[i] % (i + 1)是否等于0,如果不等于0一定无解。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N],mp[N];
inline void solve(){
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]++;
for(int i=1;i<k;i++){
if(mp[i]%(i+1)){
cout<<"NO";return;
}
mp[i+1]+=mp[i]/(i+1);
}
cout<<"YES";
}
int main(){
solve();
}