A - Yogurt Sale
判断单价
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n,a,b;
cin>>n>>a>>b;
if(a<=b*1.0/2)cout<<n*a<<endl;
else cout<<(n/2)*b+(n%2)*a<<endl;
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin>>t;
//t=1;
while(t--)solve();
return 0;
}
B - Progressive Square
- 用map存储给定数组中每个数的出现次数。
- 由题意,可知左上角必然是最小的数,以数组中最小值为起点。
- 推出矩阵中的每一个数,如果这个数存在于给定数组,则ans+1,同时map中这个数对应出现次数减1,意为该数已经被标记了一次。
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve(){
int n,c,d,a=0x3f3f3f3f;
cin>>n>>c>>d;
map<int,int>m;
int x;
for(int i=1;i<=n*n;i++){
cin>>x;m[x]++;a=min(a,x);
}
int b=a,ans=0;
for(int i=1;i<=n;i++){
for(int i=1;i<=n;i++){
if(m[a])m[a]--,ans++;
a+=d;
}
b+=c;a=b;
}
if(ans!=n*n)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin>>t;
while(t--)solve();
return 0;
}
C - Inhabitant of the Deep Sea
- 易知,如果操作次数>数组和,则必然可以全部消灭,直接特判。
- 反之,则最后一定会剩下至少一个数无法被消灭。
- 可以推出,从两边往中间消数,则左右操作次数相等或左边多操作一次,暴力循环即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve(){
int n,k,sum=0;
cin>>n>>k;
vector<int>a(n+1);
for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
if(k>=sum){cout<<n<<endl;return ;}
int l=(k+1)/2,r=k/2,ans=0;
for(int i=1;i<=n;i++){
if(l>=a[i]){l-=a[i],ans++;}
else {break;}
}
for(int i=n;i>=1;i--){
if(r>=a[i]){r-=a[i],ans++;}
else break;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin>>t;
//t=1;
while(t--)solve();
return 0;
}
D - Inaccurate Subsequence Search
- 用队列设置一个滑动窗口
- 设置两个map,分别记录:①当前窗口中符合条件的数的出现次数,以便判断次数是否能达到需求;②所需的每个数的个数
- 每次移动窗口时改变两个map的值。符合要求则答案+1
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve(){
int n,m,k;
cin>>n>>m>>k;
map<int,int>mp,mb;
vector<int>a(n+1),b(m+1);
queue<int>q;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++){
cin>>b[i];
mp[b[i]]++;
q.push(a[i]);
}
int pos=0,ans=0;
for(int i=1;i<=m;i++){
if(mp[a[i]]&&mb[a[i]]<mp[a[i]]){
pos++;
}
mb[a[i]]++;
}
if(pos>=k)ans++;
for(int i=m+1;i<=n;i++){
if(mp[q.front()]&&mb[q.front()]<=mp[q.front()])pos--;
mb[q.front()]--;
q.pop();
q.push(a[i]);
if(mp[a[i]]&&mb[a[i]]<mp[a[i]])pos++;
mb[a[i]]++;
if(pos>=k){
ans++;
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin>>t;
//t=1;
while(t--)solve();
return 0;
}
E - Long Inversions
注意:1^1=0 0^1=1
因此,可以通过异或实现变换
(1-x也可以实现)
- 设置一个pos数组,作为变换目标的标记
- 枚举k值
- 最开始找数字0,找到就在当前索引+k处标记为1,目标从找0变成找1。(遇到的第一个1逻辑上会在"操作"后变成0,因此1是下一次寻找的目标)
- 到标记的索引再变目标(说明变换区域结束了),以此类推
#include<bits/stdc++.h>
#define ll long long
using namespace std;
void solve(){
int n;
string s;
cin>>n>>s;
vector<int>a(n+1);
for(int i=1;i<=n;i++)a[i]=s[i-1]=='1';
for(int k=n;k>0;k--){
int find=0,flag=1;
vector<int>pos(n+2);
for(int i=1;i<=n;i++){
find^=pos[i];
if(find==a[i]){
if(i+k-1>n){flag=0;break;}
pos[i+k]=1;
find^=1;
}
}
if(flag){cout<<k<<endl;return ;}
}
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin>>t;
//t=1;
while(t--)solve();
return 0;
}