ABC365的C - Transportation Expenses
二分,给定一个上限m,那么l=0,r=m。每次得到中间的mid值,然后遍历数组,sum+=min(mid,a[i])得到当前mid这时候的sum值,看这个值跟m比大小,如果小,那么说明l可以变成mid再往前走,如果大了,那就r变成mid+1,再制造出来的mid就会小了。当然还需要看一下全部a[i]加起来的和跟m比一下大小,如果这个sum小了,那就可以是无限大的了。
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef long long ll;
bool cmp(int a,int b)
{
return a>b;
}
void solve() {
ll sum1=0,sum2=0,n,m;cin>>n>>m;
vector<ll> a(n+1,0);
for(ll i=1;i<=n;i++)
{cin>>a[i];sum1+=a[i];}
ll l=0,r=m,mid=m/2;
while(l<r)
{
mid=(l+r)/2;
for(int i=1;i<=n;i++)
{
sum2+=min(mid,a[i]);
}
if(sum2<=m){l=mid+1;}
else {r=mid;}
sum2=0;
}
if(sum1<=m){cout<<"infinite"<<endl;}
else{cout<<r-1<<endl;}
return ;
}
int main(){
int T;cin >> T;
while(T--){
solve();
}
return 0;
}
CF Round963B. Parity and Sum
唉,气,vector居然比直接开数组要慢,直接TLE,题意简单,首先一种特殊情况是全部都是奇数或者偶数,这种直接return0;就行,然后是大头因为每次奇偶相加都是奇数,所以最后必然全是奇数。那么找到奇数最大数,和偶数最大数,尽量做到一次就能造出最大的maxi,啊对还要注意的一个点是要sort一下从小到大遍历,因为有可能maxi加前面小的加着加着可能就大了,但是遇到第一次m比v[i]小了之后,就可以直接把最大的那个偶数给加上去了,即那一步直接替换成跟最大偶数的交换。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
typedef long long ll;
bool cmp(int a,int b)
{
return a>b;
}
void solve() {
int n,ans=0,flag1=0,flag2=0,cnt=0;cin>>n;
ll v[n+10];
//vector<ll> id(N,0);
int k=1;ll maxi=0,maxi2=0,pos=0;
for(int i=1;i<=n;i++)
{
cin>>v[i];
if(v[i]%2==0){cnt++;if(maxi2<v[i]){maxi2=v[i];pos=i;}}
else {maxi=max(maxi,v[i]);}
if(i==1){flag1=v[i]%2;}
else {if(v[i]%2!=flag1){flag2=1;}}
}
if(!flag2){cout<<0<<endl;return ;}
int m=1;
sort(v+1,v+1+n);
//sort(id.begin()+1,id.begin()+k);
//for(int i=1;i<k;i++)cout<<id[i]<<' ';
//cout<<maxi<<endl;
//if(maxi<maxi2){cnt++;maxi=maxi+maxi2;maxi+=maxi2;v[pos]=maxi;}
//if(maxi<maxi2){maxi=maxi+maxi2;cnt++;}
for(int i=1;i<=n;i++)
{
//if(i==pos){if(maxi<maxi2){cnt++;maxi=maxi+maxi2;maxi+=maxi2;v[pos]=maxi;}continue;}
if(v[i]<maxi&&v[i]%2==0){v[i]=v[i]+maxi;maxi=v[i];}
else if(v[i]%2==0&&v[i]>maxi){cnt++;maxi=v[i]+maxi2+maxi;}
}
cout<<cnt<<endl;
}
int main(){
int T;cin >> T;
while(T--){
solve();
}
return 0;
}