Codeforces 521D. Shop 题解

题目链接:D. Shop

题目大意:洛谷


题解:三种操作,先考虑顺序。操作 1 最先,2 其次,3 最末,证明显然。然后如果进行操作 1,那么肯定对于任意一个数只操作 1 次,并且一定赋为最大值,这也显而易见,所以我们可以将赋值操作转换为加法操作。

对于同一个数的加法操作总是从大向小加肯定不劣,所以我们将同一个数的加法从大往小排序,这样的话每一次加法可以转换为当前数乘上一个浮点数,这样的话就转换为了操作 3。

现在我们只有操作 3 了,从大向小排序,贪心取即可,最后将 1,2,3操作的顺序调换一下就可以了。时间复杂度(O(nlog n))

代码:。

#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
void read(int &a){
	a=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		a=(a<<1)+(a<<3)+(c^48);
		c=getchar();
	}
}
typedef long long ll;
const int Maxn=100000;
int a[Maxn+5];
int k,n,m;
int op[Maxn+5];
vector<pair<int,int> > q[Maxn+5][3];
int id[Maxn+5],len;
vector<pair<double,int> > b;
bool cmp(int p,int q){
	if(op[p]==op[q]){
		return p<q;
	}
	return op[p]<op[q];
}
int main(){
	read(k),read(n),read(m);
	for(int i=1;i<=k;i++){
		read(a[i]);
	}
	for(int i=1;i<=n;i++){
		read(op[i]);
		int pos,x;
		read(pos),read(x);
		q[pos][op[i]-1].push_back(make_pair(x,i));
	}
	for(int i=1;i<=k;i++){
		if(!q[i][0].empty()){
			sort(q[i][0].begin(),q[i][0].end());
			if(q[i][0].back().first>a[i]){
				q[i][1].push_back(make_pair(q[i][0].back().first-a[i],q[i][0].back().second));
			}
		}
		if(!q[i][1].empty()){
			sort(q[i][1].begin(),q[i][1].end(),greater<pair<int,int> >());
			ll sum=a[i];
			for(int j=0;j<(int)q[i][1].size();j++){
				b.push_back(make_pair(1.0*(sum+q[i][1][j].first)/sum,q[i][1][j].second));
				sum+=q[i][1][j].first;
			}
		}
		if(!q[i][2].empty()){
			for(int j=0;j<(int)q[i][2].size();j++){
				b.push_back(make_pair(1.0*q[i][2][j].first,q[i][2][j].second));
			}
		}
	}
	sort(b.begin(),b.end(),greater<pair<double,int> >());
	for(int i=0;i<m&&i<(int)b.size();i++){
		id[++len]=b[i].second;
	}
	sort(id+1,id+1+len,cmp);
	printf("%d
",len);
	for(int i=1;i<=len;i++){
		printf("%d ",id[i]);
	}
	puts("");
	return 0;
}
原文地址:https://www.cnblogs.com/withhope/p/13597915.html