P1873 [COCI 2011/2012 #5] EKO / 砍树 题解
其实这是一篇多题的题解,放在一起了。
P5019 [NOIP2018 提高组] 铺设道路 && P1969 [NOIP2013 提高组] 积木大赛 && P3078 [USACO13MAR] Poker Hands S
大的肯定包含小的,所以只需两项两项考虑,大的单独填。
这里注意,和以前有一题求增大后减小的策略是不一样的。那一题(我忘了什么题qaq)借助了栈。
#include<bits/stdc++.h>
using namespace std;
int n,road[100001];
long long cnt;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&road[i]);
for(int i=1;i<=n;i++){
if(road[i]>road[i-1]) cnt+=road[i]-road[i-1];
}
printf("%lld",cnt);
return 0;
}
P1873 [COCI 2011/2012 #5] EKO / 砍树
这题有二分做法(我也是写的二分),但是在这里讲一下贪心(其实也不是贪心,但我叫它贪心)。
肯定是需要单调性的,所以从大到小排序。考虑我们砍到第
二分代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,h[1000005],l,r,mid,hi;
long long len;
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&h[i]);
hi=max(hi,h[i]);
}
l=1,r=hi;
while(l<=r){
mid=(l+r)/2;
len=0;
for(int i=1;i<=n;++i){
if(h[i]>mid) len+=h[i]-mid;
}
if(len<m) r=mid-1;
else l=mid+1;
}
printf("%d",l-1);
return 0;
}
贪心代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,pos,temp;
int a[1000005];
bool cmp(int a,int b){
return a>b;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
sort(a+1,a+n+1,cmp);
for(pos=2;pos<=n&&temp<m;++pos) temp+=(pos-1)*(a[pos-1]-a[pos]);
printf("%d",a[pos-1]+(temp-m)/(pos-2));
return 0;
}
现写的,热乎呢。还是很好写的。
P6446 [COCI2010-2011#1] TABOVI
#include<bits/stdc++.h>
using namespace std;
int n,a[1005],b[1005],ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=n;++i) scanf("%d",&b[i]),a[i]=b[i]-a[i];
for(int i=1;i<=n;++i){
if(a[i]>0&&a[i-1]>0) ans+=max(0,a[i]-a[i-1]);
else if(a[i]<0&&a[i-1]<0) ans+=max(0,a[i-1]-a[i]);
else ans+=abs(a[i]);
}
printf("%d",ans);
return 0;
}
P2440 木材加工
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[100005];
bool check(int x){
int ans=0;
for(int i=1;i<=n;++i) ans+=a[i]/x;
return ans>=m;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
int l=0,mid,r=1e8+1;
while(l<r){
mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%d",l);
return 0;
}
P1182 数列分段 Section II
#include<bits/stdc++.h>
using namespace std;
int n,m,l,mid,r;
int a[100005];
bool check(int x){
int num=1,temp=0;
for(int i=1;i<=n;++i){
if(temp+a[i]>x) ++num,temp=a[i];
else temp+=a[i];
if(num>m) return false;
}
return true;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),l=max(l,a[i]),r+=a[i];
while(l<r){
mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d",l);
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现