CF521D Shop

贪心

先分析一下性质

  1. 每个位置的赋值操作至多做一次

  2. 每个位置先加后乘,赋值和加法都可以化为乘法

加法和乘法一定按b排序,于是加法内部顺序是固定的

所以可以排序后算出每次相当于乘多少,然后将所有操作按 b 再排序取前 m 个

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+11;
struct opt_{
	int ty,x,sum;
	int num;
	double xl;
}cf[N];
int n,k,m,sl;
int a[N];
int maxx[N],num[N];
vector<opt_> vct[N];
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
bool cmpxl(opt_ a,opt_ b){return a.xl>b.xl;}
bool cmps(opt_ a,opt_ b){return a.sum>b.sum;}
bool cmpx(opt_ a,opt_ b){return a.x!=b.x?a.x<b.x:a.ty<b.ty;}
signed main()
{
	n=read();
	m=read();
	k=read();
	for(int i=1;i<=n;++i) a[i]=read();
	for(int ty,x,y,i=1;i<=m;++i)
	{
		ty=read();
		x=read();
		y=read();
		if(ty==1){if(maxx[x]<y){maxx[x]=y;num[x]=i;}}
		else if(ty==2) vct[x].push_back((opt_){2,x,y,i});
		else cf[++sl]=(opt_){3,x,y,i,(double)y};
	}
	for(int i=1;i<=n;++i)
	{
		if(maxx[i]>a[i]) vct[i].push_back((opt_){1,i,maxx[i]-a[i],num[i]});
		sort(vct[i].begin(),vct[i].end(),cmps);
		if(vct[i].size())
		{
			int sum=vct[i][0].sum+a[i];
			vct[i][0].xl=(double)sum/a[i];
			cf[++sl]=vct[i][0];
			for(int j=1;j<vct[i].size();++j)
			{
				vct[i][j].xl=(double)(sum+vct[i][j].sum)/sum;
				sum+=vct[i][j].sum;
				cf[++sl]=vct[i][j];
			}
		}
	}
	sort(cf+1,cf+sl+1,cmpxl);
	k=min(sl,k);
	sort(cf+1,cf+k+1,cmpx);
	cout<<k<<endl;
	for(int i=1;i<=k;++i) printf("%lld ",cf[i].num);
	return 0;
}

posted @ 2021-11-02 07:08  sitiy  阅读(55)  评论(0编辑  收藏  举报