Codeforces Round #600 (Div. 2)
A. Single Push
题目大意:给定两个数组,问你能不能给A数组连续一段加一个数字,使得其等于B数组。
分析:模拟一下即可,就不用想太多了。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+7; typedef long long ll; ll a[maxn],b[maxn]; int main(){ int t,n; cin>>t; while(t--){ cin>>n; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<n;i++) cin>>b[i]; ll tol=0; int l,r; for(int i=0;i<n;i++) tol+=b[i]-a[i]; if(!tol) cout<<"YES"<<endl; else{ for(int i=0;i<n;i++){ if(a[i]!=b[i]){ l=i; break; } } for(int i=n-1;i>=0;i--){ if(a[i]!=b[i]){ r=i; break; } } ll re=b[l]-a[l]; bool f=true; for(int i=l;i<=r;i++){ if(re+a[i]!=b[i]){ f=false; break; } } if(f){ if(re<=0) cout<<"NO"<<endl; else cout<<"YES"<<endl; } else{ cout<<"NO"<<endl; } } } return 0; }
B. Silly Mistake
题目大意:给定一个数组,然后正整数表示这个人到达,负数代表其相反数这个人离开,问你每天有多个人到达(到达且离开才表示一次成功)。
分析:也是模拟,但是比第一个稍微复杂一点。需要逻辑思维比较清楚。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+7; int cnt[maxn]; map<int,int> vis; set<int> s; int main() { int n, x; cin >> n; bool f = true; int day = 1; for (int i = 0; i < n; i++) { cin >> x; if (x < 0) { if (s.count(-x)) { s.erase(s.find(-x)); } else { f = false; } } else { if(vis[x]==day) { if (s.size() || s.find(x) != s.end()) f = false; } vis[x] = day; cnt[day]++; s.insert(x); } if (!s.size() && i != n - 1) day++; } if (s.size()) f = false; if (!f) cout << -1 << endl; else { cout << day << endl; for (int i = 1; i <= day; i++) { cout << 2*cnt[i] << (i == day ? '\n' : ' '); } } return 0; }
C. Sweets Eating
题目大意:每天只能吃m个甜点,第i天吃第s个甜品的花费是i*a[s]。问你怎么样能使得吃每个甜品的花费最小。
分析:线性dp,如果i小于m,dp[i+1]=sum,否则,dp[i+1]=dp[i-m+1]+sum。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+7; typedef long long ll; ll a[maxn]; ll dp[maxn]; int main(){ int n,m; cin>>n>>m; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n,less<ll>()); ll sum=0; for(int i=0;i<n;i++){ sum+=a[i]; if(i<m) dp[i+1]=sum; else dp[i+1]=dp[i-m+1]+sum; } for(int i=1;i<=n;i++) cout<<dp[i]<<(i==n?'\n':' '); return 0; }