Educational Codeforces Round 108 (Rated for Div. 2)(C~D)

传送门

C. Berland Regional

题意:一共2e5个学生,告诉你他们的学校和能力。设k表示一个队伍的人数,一个学校可以派出任意个队伍。问当k从1至n时,所有学校能派出最大能力之和。

题解:考虑暴力解法,先将学生放入学校的vector排序,枚举k与学校,易知学校人数不能整除k时,将会有余数个人不能加入和,这里用前缀和优化一下即可。但目前还是个n方的解法,这里我们剪枝一下。当某个学校人数小于k,这个学校就我不想再枚举。这里我们对学校按人数排序,用一个单指针记入第一个学校,当第一个学校人数小于k时,就使指针往后移。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define ll long long
const ll N=2e5+7;
ll t,n,a[N],b[N],sum[N];
vector<ll>ho[N];
pair<ll,ll>pos[N];
bool cmp(ll a,ll b){
	return a>b;
}
int main(){
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		for(int i=1;i<=n;i++){
			ho[i].clear();
			sum[i]=0;
		}
		for(int i=1;i<=n;i++){
			scanf("%lld",&a[i]);
		}
		for(int i=1;i<=n;i++){
			scanf("%lld",&b[i]);
		}
		for(int i=1;i<=n;i++){
			ho[a[i]].push_back(b[i]);
		}
		for(int i=1;i<=n;i++){
			sort(ho[i].begin(),ho[i].end(),cmp);
		}
		for(int i=1;i<=n;i++){
			ll len=ho[i].size();
			pos[i].first=len;
			pos[i].second=i;
			for(int j=1;j<len;j++){
				ho[i][j]+=ho[i][j-1];
			}
		}
		sort(pos+1,pos+1+n);
		int p=1;
		for(int i=1;i<=n;i++){
			while(p<=n&&pos[p].first<i){
				p++;
			}
			for(int j=p;j<=n;j++){
				ll len=pos[j].first;
				ll now=pos[j].second;
				ll to=len-len%i;
				sum[i]+=ho[now][to-1];
			}
		}
		for(int i=1;i<=n;i++){
			printf("%lld ",sum[i]);
		}puts("");
	}
}

D. Maximum Sum of Products

题意:给一个数组a,与数组b,你可以倒置a中一段,求最大的ai*bi之和。

题解:这种题目,很明显不能贪心,所以要暴力求解。枚举a中的每一段,然后每一段由于会倒置,所以贡献要重新算,这样的复杂度是O(n * n * n),我们发现每一段的贡献可以dp算出来,所以时间降至n方。

#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
const ll N=5007;
ll n,a[N],b[N],px[N];
ll f[N][N];
ll dfs(ll l,ll r){
	if(l==r){
		return a[l]*b[l];
	}
	else if(l+1==r){
		return a[l]*b[r]+a[r]*b[l];
	}
	if(f[l][r]!=-1){
		return f[l][r];
	}
	return f[l][r]=a[l]*b[r]+a[r]*b[l]+dfs(l+1,r-1);
}
int main(){
	memset(f,-1,sizeof(f));
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%lld",&b[i]);
		px[i]=px[i-1]+a[i]*b[i];
	}
	ll ans=0;
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			ans=max(ans,px[i-1]+px[n]-px[j]+dfs(i,j));
		}
	}
	printf("%lld\n",ans);
}
posted @ 2021-04-30 10:29  ccsu_madoka  阅读(57)  评论(0编辑  收藏  举报