羊圈
題目描述 ZYC的農場有N(1<=N<=100,000)塊連續的區域排成一排,每塊區域上都有確定數量的羊(每塊區域不超過2000千只)。?
現在ZYC想要將一些區域用圍墻圍起來,作為信息社的優秀成員,當然要給自己出點難題:他希望圍起來的區域里羊的總數/區域數的值最大,并且保證圍起來的區域數不小于M。? 輸入 第一行包括兩個整數,分別表示N和M?
以下N行每行一個正整數,表示對應區域羊的數量(單位千只)? 輸出 輸出最大平均數(單位只)? 樣例輸入 10 6 6 4 2 10 3 8 5 9 4 1 樣例輸出 6500
解析:由于很明顯,暴力是n*n級的算法,很明顯TLE,最多只有71分,所以我就用DP優化了一下,代碼如下: #include<bits/stdc++.h> using namespace std; struct Nd {long long x,sum; }; Nd dp[100001]; long long a[100001]; long long ans; int main() {long long n,m;scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]*=1000;long long sum2=0;for(int i=1;i<=m;i++) sum2+=a[i];dp[m].x=m;dp[m].sum=sum2;for(int i=m+1;i<=n;i++){dp[i].sum=dp[i-1].sum+a[i];dp[i].x=dp[i-1].x+1;int max_n=0,max_ans,max_ans2,j_sum=0;for(int j=dp[i].x;j>=m;j--){if(max_n<(dp[i].sum-j_sum)/j){max_n=(dp[i].sum-j_sum)/j;max_ans=j;max_ans2=j_sum;}j_sum+=a[i-j+1];}dp[i].sum-=max_ans2;dp[i].x=max_ans;}for(int i=m;i<=n;i++){ans=max(ans,dp[i].sum/dp[i].x);} //cout<<endl;cout<<ans;return 0; }
現在ZYC想要將一些區域用圍墻圍起來,作為信息社的優秀成員,當然要給自己出點難題:他希望圍起來的區域里羊的總數/區域數的值最大,并且保證圍起來的區域數不小于M。? 輸入 第一行包括兩個整數,分別表示N和M?
以下N行每行一個正整數,表示對應區域羊的數量(單位千只)? 輸出 輸出最大平均數(單位只)? 樣例輸入 10 6 6 4 2 10 3 8 5 9 4 1 樣例輸出 6500
解析:由于很明顯,暴力是n*n級的算法,很明顯TLE,最多只有71分,所以我就用DP優化了一下,代碼如下: #include<bits/stdc++.h> using namespace std; struct Nd {long long x,sum; }; Nd dp[100001]; long long a[100001]; long long ans; int main() {long long n,m;scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]*=1000;long long sum2=0;for(int i=1;i<=m;i++) sum2+=a[i];dp[m].x=m;dp[m].sum=sum2;for(int i=m+1;i<=n;i++){dp[i].sum=dp[i-1].sum+a[i];dp[i].x=dp[i-1].x+1;int max_n=0,max_ans,max_ans2,j_sum=0;for(int j=dp[i].x;j>=m;j--){if(max_n<(dp[i].sum-j_sum)/j){max_n=(dp[i].sum-j_sum)/j;max_ans=j;max_ans2=j_sum;}j_sum+=a[i-j+1];}dp[i].sum-=max_ans2;dp[i].x=max_ans;}for(int i=m;i<=n;i++){ans=max(ans,dp[i].sum/dp[i].x);} //cout<<endl;cout<<ans;return 0; }
很明顯,這樣雖然優化了一些,但還是接近n*n,所以只有79分。但這樣還是不行,我就想到了二分,二分求答案。代碼如下:
#include<bits/stdc++.h> using namespace std; const int NR=100000+5; int n,m; long long a[NR]; long long sum[NR]; long long sum2[NR]; long long l=-1e6,r=1e6;//二分左右端點 bool check(long long x)//***核心*** check函數 {for(int i=n;i>=1;i--)sum2[i]=max(a[i]-x,sum2[i+1]+a[i]-x);//i往后的羊數最多比x大幾 for(int i=1;i<=n-m+1;i++){if(sum[i+m-1]-sum[i-1]>=m*x)//如果取m個區域 return 1;if(sum[i+m-1]-sum[i-1]+sum2[i+m]>=x*m)//取>m個區域 return 1;}return 0; } int main() {scanf("%d%d",&n,&m);//讀入 for(int i=1;i<=n;i++){scanf("%lld",&a[i]);a[i]*=1000;sum[i]=sum[i-1]+a[i];}while(l<=r)//二分模板 {int mid=(l+r)/2;if(check(mid)) l=mid+1;else r=mid-1;}cout<<r<<endl;return 0; }
轉載于:https://www.cnblogs.com/chen-1/p/11175863.html
總結
- 上一篇: spring第一个小例子(Spring_
- 下一篇: DataList自定义分页