程序設計思維與實踐 Week4 作業

這裏是引用

思路:n^2的做法,貪心,先按照價值升序排序,每次從ddl往前找空餘位置,如果能放進去,就標記一下,不然就放棄。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,t;
bool b[1001];
struct da{int t,x;}s[1001];
int cmp(const da &x,const da &y)
{
	return x.x!=y.x?x.x>y.x:x.t>y.t;
}
int main()
{
//	freopen("1.txt","r",stdin);
	scanf("%d",&t);
	while(t--)
	{
		int ans=0;
		scanf("%d",&n);memset(b,0,sizeof b);
		for(int i=1;i<=n;i++) scanf("%d",&s[i].t);
		for(int i=1;i<=n;i++) scanf("%d",&s[i].x);
		sort(s+1,s+n+1,cmp);
		for(int i=1;i<=n;i++)
		{
			bool flag=false;
			for(int j=s[i].t;j>=1;j--) 
			  if(!b[j]) {b[j]=true,flag=true;break;}
			if(!flag) ans+=s[i].x;
		}
		printf("%d\n",ans);
	}
	return 0;
}

總結:有點二位偏序的意思,只寫了n^2的做法,更優的做法的話可以考慮倒序枚舉,這樣可以降掉一維,然後用數據結構維護當前的max,每次取當前的最優值即可,因爲是動態的,所以用堆比較好寫一點。還有線段樹維護區間最右點的解法,在n ^ 2基礎上稍加改動即可。

這裏是引用

思路:二分,n^2 log n^2 ,將ab合爲一個長度爲n^ 2的數組,cd也合爲一個長度爲n^2的數組,然後二分cd數組,計算複合條件的數。

#include<cstdio>
#include<algorithm>
#define MAXN 4001
using namespace std;
int n,tot,a[MAXN],b[MAXN],c[MAXN],d[MAXN],s[MAXN*MAXN];
int erfenr(int x)
{
	x=-x;
	int l=1,r=tot,ans=-1;
	while(l<=r)
	{
		int mid=l+r>>1;
		if(s[mid]==x) ans=mid,l=mid+1;
		else if(s[mid]>x) r=mid-1;
		else l=mid+1;
	}
	return ans;
}
int erfenl(int x)
{
	x=-x;
	int l=1,r=tot,ans=-1;
	while(l<=r)
	{
		int mid=l+r>>1;
		if(s[mid]>=x) ans=mid,r=mid-1;
		else l=mid+1;
	}
	return ans;
}
int main()
{

	int ans=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	  	s[++tot]=a[i]+b[j];
	sort(s+1,s+tot+1);
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	  {
	  	int l=erfenl(c[i]+d[j]);
	  	int r=erfenr(c[i]+d[j]);
		if(r==-1) continue;
	  	ans+=r-l+1;
	  }
	printf("%d",ans);
	return 0;
}

總結:二分模板題,map會T,而且這題略卡常。

這裏是引用
思路:二分答案。先按照a[i]升序排序,二分答案x,檢驗滿足 a[i]+x<=a[j]的對數tot,如果tot>中位數條件就 向左二分,反之向右。檢驗的時候二分查找,可以將條件改爲找大於a[i]+x的lower_bound,然後位置減一即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
int n,a[100001],ans;
int ffind(int x)
{
	x++;
	int l=1,r=n,mid,tot=n+1;
	while(l<=r)
	{
		mid=l+r>>1;
		if(a[mid]>=x) tot=mid,r=mid-1;
		else l=mid+1;
	}
	return tot-1;
}
bool check(int x)
{
	LL tot=0;
	for(int i=1;i<=n;i++)
	{
		tot+=ffind(a[i]+x)-i;
	}
	return tot*2>=((n-1)*n+1)/2;
} 
void erfen(int l,int r)
{
	int mid;
	while(l<=r){
		mid=l+r>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	return ;
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		ans=0;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		sort(a+1,a+n+1);
		erfen(0,a[n]-a[1]);
		printf("%d\n",ans);
	}
	return 0;
}

總結:思路不難想,有點細節沒處理好,導致寫了很久,以後要認真分析,不要急着碼(???老毛病又犯了)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章