Codeforces Round #723 Div. 2个人代码
写出来四题,开心QWQ
A. Mean Inequality
题意:给一个数n,然后给2*n个数,让我们构造一个数列满足数列中任意一项都满足
bi≠(bi−1+bi+1)/2
其中满足相同的数最多n项
题目解析:只需要先将数组内的数排序,然后依次以1,n+1,2,n+2…这样输出。
#include<bits/stdc++.h>
const int N=1e9+7;
using namespace std;
int n,t;
int a[100005];
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=2*n;i++){
cin>>a[i];
}
sort(a+1,a+1+2*n);
for(int i=1;i<=n;i++){
cout<<a[i]<<" "<<a[i+n]<<" ";
}
cout<<endl;
}
return 0;
}
题意很简单,给一个t,后面t个数,让我们依次判断这t个数能否由11,111,1111,11111,111111,1111111…相加所得。
题目解析:首先推出1111=11 * 101,11111=111*100+11……,显然四个1以上的数字都能由11和111组成,我们只需要判断所给数能否被若干个111和11相加组成就行了。
其次当111的数量大于10的时候,显然能将每11个111变为111个11,所以111的数量一定是0到10个(其实算到这里已经可以全部枚举一遍来判断是否能组成)
由因为111%11=1,所以若通过111和11能组成n,则111的个数一定是n%11个,所以根据以上结论,我们可以写出以下代码
这题是个结论题,知道结论可以秒杀(跟a*b-a-b有关,后面有时间再来补),像我不知道结论花费了好多时间在前面的证明。
#include<bits/stdc++.h>
const int N=1e9+7;
using namespace std;
long long n,m,t,k;
int main(){
cin>>t;
while(t--){
cin>>n;
k=n%11;
n-=k*111;
if(n>=0&&n%11==0){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
return 0;
}
c1和c2一起写的,就是后悔贪心板子题
题意:给你n瓶药,喝完每个药你会获得一个健康值(可为负),你要从1喝到n(你可以选择喝或者不喝),但你要保证你的健康值大于0,求你可以喝的最大药品数量
题目解析:典型的后悔贪心,
先遍历一遍数组,喝下所有健康值为正数的药品,并记录在一个数组中
第二部再次遍历一遍数组,遇见负的则入队,如果喝下这瓶药使你的健康值为负数,则不要喝前面负的健康值最小的药(这里需要使用单调优先队列)
最后只需要将你喝下去的负健康值药瓶数和正健康值瓶数的药相加就可以啦!
(此题需要开long long)
(以下代码可通过c1和c2)
备注:此题上面两个遍历可以写道一个for循环当中,正数也可加入单调优先队列,只是个人为了便于自己理解才写成的两个for循环。
#include<bits/stdc++.h>
const int N=1e9+7;
using namespace std;
long long n,m;
long long sum,ans;
long long a[200005];
long long dp[200005];
priority_queue<long long, vector<long long>, greater<long long> > q;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>=0){
sum+=a[i];
ans++;
}
dp[i]=sum;
}
sum=0;
for(int i=1;i<=n;i++){
if(a[i]<0){
sum+=a[i];
q.push(a[i]);
if(sum+dp[i]<0){
sum-=q.top();
q.pop();
}
}
}
cout<<ans+q.size();
return 0;
}