Codeforces Round 938 (Div. 3)题解(A-E)
A. Yogurt Sale
题意:输入一份酸奶a元,两份b元,求买n份酸奶最少要多少钱。
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6+7;
void solve(){
int n,a,b; cin>>n>>a>>b;
if(n%2==0){
if(a*2<=b) cout<<a*n<<'\n';
else cout<<b*n/2<<'\n';
}
else{
if(a*2<=b) cout<<a*n<<'\n';
else{
cout<<a+b*(n-1)/2<<'\n';
}
}
return;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
B. Progressive Square
题意:给n*n个数,问这些数能否排成满足
$ a_{i+1,j} = a_{i,j} + c $
$ a_{i,j+1} = a_{i,j} + d $
思路:
显然\(a_{11}\)最小,
将数组存在哈希表里,让给定数组中最小的数作为\(a_{11}\),按题意补充矩阵中剩余元素,若对应数不存在输出NO,存在输出YES
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const ll N = 1e8+7;
void solve(){
ll n,c,d; cin>>n>>c>>d;
ll mn=1e11;
map<int,int> vis;
for(ll i=1;i<=n*n;i++){
ll num; cin>>num;
if(mn>num) mn=num;
vis[num]++;
}
ll mtx[n+7][n+7];
mtx[1][1]=mn;
ll temp;
for(ll i=2;i<=n;i++){
temp=mtx[1][i]=mtx[1][i-1]+c;
if(vis[temp]>0) vis[temp]--;
else{
cout<<"NO"<<'\n';
return;
}
}
for(ll i=2;i<=n;i++){
temp=mtx[i][1]=mtx[i-1][1]+d;
if(vis[temp]>0) vis[temp]--;
else{
cout<<"NO"<<'\n';
return;
}
}
for(ll i=2;i<=n;i++){
for(ll j=2;j<=n;j++){
temp=mtx[i][j]=mtx[i][j-1]+c;
if(vis[temp]>0) vis[temp]--;
else{
cout<<"NO"<<'\n';
return;
}
}
}
cout<<"YES"<<'\n';
return;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
C. Inhabitant of the Deep Sea
题意:有n次射击机会,每次向最左和最右交替射击,每次射击-1生命。能击沉多少船。
思路:完全模拟肯定超时,数据规模是1e15
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
void solve(){
ll n,k; cin>>n>>k;
ll ft=(k+1)/2; ll bk=k/2;
ll ans=0;
ll ship[n+7];
ll sum=0;
for(ll i=1;i<=n;i++){
cin>>ship[i];
sum+=ship[i];
}
if(sum<=k){
cout<<n<<'\n';
return;
}
ll l=1,r=n;
while(ft>0){
if(ft>=ship[l]) ans++;
ft-=ship[l];
l+=1;
}
while(bk>0){
if(bk>=ship[r]) ans++;
bk-=ship[r];
r-=1;
}
cout<<ans<<'\n';
return;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
D. Inaccurate Subsequence Search
题意:有长度为n的数组a和长度为m的数组b,求a长度为m的子段中,有多少个子段是“好的”,即至少k个元素与数组b中的元素匹配。
思路:b存哈希表vis,写一个缓存的哈希表tmp,对a遍历,每次重新对tmp重新初始化
代码实现:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int MXN=1e6+7;
void solve(){
int n,m,k; cin>>n>>m>>k;
int ans=0;
int a[n+7],b[m+7];
map<int, int> vis;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
cin>>b[i];
vis[b[i]]++;
}
for(int i=1;i<=n-m+1;i++){
int sum=k;
map<int, int> tmp;
for(int t=1;t<=m;t++){
tmp[b[t]]=vis[b[t]];
}
for(int j=0;j<m;j++){
if(tmp[a[i+j]]>0){
sum--;
tmp[a[i+j]]--;
}
}
if(sum<=0) ans++;
// cout<<ans<<' ';
}
cout<<ans<<'\n';
return;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
上述代码不出所料的在test4超时了,用滑动窗口
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int MXN=1e6+7;
void solve(){
int n,m,k; cin>>n>>m>>k;
int a[n+7],b[m+7];
map<int, int> vis;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
cin>>b[i];
vis[b[i]]++;
}
ll res=0,ans=0;
map<int, int> tmp;
for(int i=1;i<=n;i++){
if(i>m){
if(tmp[a[i-m]]<=vis[a[i-m]]) res--;
tmp[a[i-m]]--;
}
if(tmp[a[i]]<vis[a[i]]) res++;
tmp[a[i]]++;
if(i>=m && res>=k) ans++;
}
cout<<ans<<'\n';
return;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
E. Long Inversions
题意:给定以0和1构成的字符串,可以选定一个长度为k的区间对0和1进行翻转,求最大能使字符串都为1的k。
思路:从长度n开始遍历,用check()检查合法。check()使用了差分数组存储是否翻转。
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int N=5010;
string s;
int n;
int d[N];//差分数组 是否操作过
int a[N];
bool check(int x){
for(int i=1;i<=n;i++) d[i]=0;
for(int i=1;i<=n;i++){
d[i]^=d[i-1]; //<1>
if((a[i]^d[i])==0){
if(i+x-1>n) return 0;
d[i]^=1;//<2>
d[i+x]^=1;//<3>
}
}
return 1;
}
// <1>-<3>记录了哪些位置进行了(奇数次)翻转操作
void solve(){
cin>>n>>s;
for(int i=1;i<=n;i++){
a[i]=s[i-1]-'0';
}
for(int i=n;i>=1;i--){
if(check(i)) {
cout<<i<<'\n';
return;
}
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}