AcWing 刷題2
阿新 • • 發佈:2022-01-29
AcWing 1227.分巧克力
思路
首先可以確定是二分,然後就是實現的細節,最開始我左邊界設為1,右邊界是把所有巧克力的總面積計算出來再除以小朋友的數量(最理想情況下),結果怎麼都不對,後來想起來,二分的話,左右邊界很大也沒太大問題,因為只需要幾次就會到正常區間了。所以直接把右邊界設為100005了,這才算是對的.....中間真的冥思苦想不知道哪裡出錯了,氣死了。
題解
#include<bits/stdc++.h> using namespace std; const int N=100005; int h[N],w[N]; int n,k; int main(void) { cin>>n>>k; int sum=0; for(int i=0;i<n;i++) cin>>h[i]>>w[i]; int l=1,r=100005,m; while(l<r) { int q=k;//小朋友數量 m=(l+r+1)/2; for(int i=0;i<n;i++) q-=(h[i]/m)*(w[i]/m); if(q>0) r=m-1; else l=m; } cout<<l<<endl; return 0; }
AcWing 795.字首和
思路
就是最基礎的字首和的思路,用一個數組F,Fi表示前i個元素的和,求區間l和r之間的數的和,只需要求Fi-Fi-1就行了
題解
#include<bits/stdc++.h> using namespace std; const int N=100005; int f[N]; int n,m,x,l,r; int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>x; f[i]=f[i-1]+x; } while(m--) { cin>>l>>r; cout<<f[r]-f[l-1]<<endl; } return 0; }
AcWing 796.子矩陣的和
思路
和前綴合一樣的原理,只不過變成了二維。(感覺和小時候數學題裡的求不規則圖形的面積有點相似,容斥原理)
重點在這兩句:
f[i][j]+=f[i][j-1]+f[i-1][j]-f[i-1][j-1];
cout<<f[c][d]-f[a-1][d]-f[c][b-1]+f[a-1][b-1]<<endl;//這個下標折磨了我半天
題解
#include<bits/stdc++.h> using namespace std; const int N=1005,M=1005; int f[N][M],s[N][M]; int n,m,q; int main() { int a,b,c,d; cin>>n>>m>>q; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>f[i][j]; f[i][j]+=f[i][j-1]+f[i-1][j]-f[i-1][j-1]; } while(q--) { cin>>a>>b>>c>>d; cout<<f[c][d]-f[a-1][d]-f[c][b-1]+f[a-1][b-1]<<endl; } return 0; }
AcWing 99.鐳射炸彈
思路
跟子矩陣的和很像,只是有幾點需要注意,我寫的時候遇到了很多問題。
如果正方形的邊長大於地圖中最大的橫縱座標,相當於每個點都能覆蓋到,那麼直接把邊長改為最大的橫縱座標的那個就好了
還有,在求二維字首和矩陣的時候,忘記了加i,j位置本身的值....
題解
#include<bits/stdc++.h>
using namespace std;
const int N=5005;
int f[N][N];
int n,m,h,l,x,y,w,ans;
int main()
{
cin>>n>>m;
if(m>5001) m=5001;
h=m;
l=m;
while(n--)
{
cin>>x>>y>>w;
f[++x][++y]+=w;
h=max(h,x);
l=max(l,y);
}
for(int i=1;i<=h;i++)
for(int j=1;j<=l;j++)
f[i][j]=f[i][j-1]+f[i-1][j]-f[i-1][j-1]+f[i][j];
for(int i=m;i<=h;i++)
for(int j=m;j<=l;j++)
ans=max(ans,f[i][j]-f[i-m][j]-f[i][j-m]+f[i-m][j-m]);
cout<<ans<<endl;
return 0;
}