1. 程式人生 > 其它 >AcWing 刷題2

AcWing 刷題2

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;
}