B - Powered Addition
题意:给定数组,可以在第x秒使其中任意的数增加2^x-1,求使其成为不递减数组的最小操作次数.
解题思路:找出从递减开始相差最大的差值,判断是2的多少倍即可.
ac代码:
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
int t,n,a[100005],i,j,m;
cin>>t;
while(t--){
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
}
int ma=a[0];
int c=0;
for(i=0;i<n;i++){
if(c<ma-a[i]){
c=ma-a[i];
}
if(a[i]>ma){
ma=a[i];
}
}
if(c==0){
cout<<"0"<<endl;
continue;
}
int mm=0,k=1;
for(i=1;;i++){
mm+=k;
if(mm>=c){
break;
}
k*=2;
}
cout<<i<<endl;
}
return 0;
}
View Code
C - Middle Class
题意:给定人数为n的数组的储蓄值和富有数x,可以进行从数组选出一部分人(包括所有人),将他们的所有储蓄再平均分配给他们,求执行操作后可以成为富有的最多人数.
解题思路:对数组进行排序,从最后一项开始求和取平均数,直至平均数小于富有数x.
ac代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
int t,n,x,i,j;
long long a[100005],sum;
cin>>t;
while(t--){
cin>>n>>x;
sum=0;
for(i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int pp=0;
for(i=n-1,j=1;i>=0;i--,j++){
sum+=a[i];
if(sum/j<x){
cout<<j-1<<endl;
pp=1;
break;
}
}
if(pp==0) cout<<n<<endl;
}
return 0;
}
View Code
D - Circle of Monsters
题意:有n个怪物环形排列,每个怪物有a[i]滴血,每次射击降低怪物1滴血,当血量小于等于0再射击会爆炸产生b[i]伤害,能伤害到下一个怪物,若炸死了下一个,也是同样爆炸,问最小射击次数使得全部怪物死亡.
解题思路:不是很懂////)
尽可能利用爆炸伤害,爆炸伤害在最优时是每个怪物都炸下一个怪物,这样爆炸伤害和就是
∑i=1n−1min(本怪物爆炸伤害,下一个怪物血量)+min(最后一个怪物爆炸伤害,第一怪物血量)
取一个爆炸伤害对自己炸的血量最少的怪物为起点,答案是sum(怪物血量和)−sum(爆炸伤害)+(爆炸贡献最小的一次爆炸伤害)
ac代码:
#include<iostream>
using namespace std;
int a[300005],b[300005];
long long int c[300005];
int main(){
int t,n,i;
long long int sum,s,mi;
cin>>t;
while(t--){
cin>>n;
sum=0;
s=0;
mi=1e13;
for(i=0;i<n;i++){
cin>>a[i];
cin>>b[i];
sum+=a[i];
}
for(i=0;i<n-1;i++){
c[i]=min(b[i],a[i+1]);
s+=c[i];
mi=min(mi,c[i]);
}
c[n-1]=min(b[n-1],a[0]);
s+=c[n-1];
mi=min(mi,c[n-1]);
cout<<sum-s+mi<<endl;
}
return 0;
}
View Code
E - Kind Anton
题意:给定长度为n的数组b,和只含有{-1,0,1}元素的数组a,可以选择一对i,j(i<j),使ai的值可以无限次加到aj上去(可以为0次!!!),求能否通过这个操作使得a数组与b数组相等.
解题思路:利用map计数,倒序遍历,判断是否含有1或-1使a[i]==b[i]
ac代码:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
long long a[100005],b[100005];
int main(){
int t,n,i,j;
int k;
cin>>t;
map<int,int>mp;
while(t--){
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
mp[a[i]]++;
}
for(i=0;i<n;i++){
cin>>b[i];
}
k=0;
for(i=n-1;i>=0;i--){
mp[a[i]]--;
if(b[i]>a[i]){
if(mp[1]>0){
continue;
}
else{
k=1;
cout<<"NO"<<endl;
break;
}
}
if(b[i]<a[i]){
if(mp[-1]>0)
continue;
else{
k=1;
cout<<"NO"<<endl;
break;
}
}
}
if(k==0)
cout<<"YES"<<endl;
mp.clear();
}
return 0;
}
View Code
F - Eugene and an array
题意:给定数组,求不含和为0的子数组的个数.
解题思路:前缀和pre[i]=pre[j],说明在ai+1~aj这一段的和为0,则所求字符串不应该包含这段,记录pre[i]所在的位置为p,则不包含子串和为0的个数为i−(p+1).
ac代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
map<ll,int> pos;
ll ans,s;
int n,x;
int main() {
cin>>n;
pos[0]=0;
int q=-1;
for(int i=1;i<=n;i++){
cin>>x;
s+=x;
if (pos.count(s)) q=max(q,pos[s]);//记录当前位置
ans+=i-q-1;
pos[s]=i;
}
cout<<ans<<endl;
}
View Code