• [CF521D] Shop


    问题描述

    Vasya plays one very well-known and extremely popular MMORPG game. His game character has k skill; currently the i -th of them equals to ai . Also this game has a common rating table in which the participants are ranked according to the product of all the skills of a hero in the descending order.

    Vasya decided to 'upgrade' his character via the game store. This store offers n possible ways to improve the hero's skills; Each of these ways belongs to one of three types:

    1. assign the i -th skill to b ;
    2. add b to the i -th skill;
    3. multiply the i -th skill by b .

    Unfortunately, a) every improvement can only be used once; b) the money on Vasya's card is enough only to purchase not more than m of the n improvements. Help Vasya to reach the highest ranking in the game. To do this tell Vasya which of improvements he has to purchase and in what order he should use them to make his rating become as high as possible. If there are several ways to achieve it, print any of them.

    输入格式

    The first line contains three numbers — k,n,m ( 1<=k<=10^5 , 0<=m<=n<=10^5 ) — the number of skills, the number of improvements on sale and the number of them Vasya can afford.

    The second line contains k space-separated numbers ai ( 1<=ai<=10^6 ), the initial values of skills.

    Next n lines contain 3 space-separated numbers tj,ij,bj ( 1<=tj<=3,1<=ij<=k,1<=bj<=10^6 ) — the type of the j -th improvement (1 for assigning, 2 for adding, 3 for multiplying), the skill to which it can be applied and the value of b for this improvement.

    输出格式

    The first line should contain a number l ( 0<=l<=m ) — the number of improvements you should use.

    The second line should contain l distinct space-separated numbers vi ( 1<=vi<=n ) — the indices of improvements in the order in which they should be applied. The improvements are numbered starting from 1 , in the order in which they appear in the input.

    样例输入

    2 4 3
    13 20
    1 1 14
    1 2 30
    2 1 6
    3 2 2

    样例输出

    3
    2 3 4

    题目大意

    n个数,有m个操作,形如:

    1,将 xi 改成vali

    2,将 xi 加上vali

    3,将 xi 乘上vali

    其中第i个操作的编号为i. 现在你可以从中选择最多k个操作(不能重复选),并按一定顺序执行,使得(prod_{i = 1}^{n}x_i)最大。

    第一行输出选择的操作个数,第二行按执行顺序输出方案。

    解析

    我们可以注意到乘法是可以随意调换顺序的,假设只有操作三,那么最后的答案就是从大到小的k个操作的值乘起来。

    再来考虑操作二。对于一个数,我们肯定优先取更大的相加。所以,把每个数的加法操作从大到小排序,那么对于一个加法操作,在执行操作之前被加数的数值是确定的。不妨也将加法转化为乘法,即把给(x)(y)变成给(x)乘上(frac{x+y}{x})。这样一个乘数是确定的。可以发现,把这样的乘法操作从大到小排序之后得到的一定是最优解。

    最后来考虑操作一。同样的道理,每个赋值操作也可以转化为乘法。而对于一个数,赋值操作最多只会有一个产生效果,我们取最大的即可。

    综上所述,我们把所有操作转化为乘法操作,然后按乘数从大到小排序,取前k个操作即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define int long long
    #define N 100002
    using namespace std;
    struct event{
    	int op,id,x,val,f;
    }t1[N],t2[N],t3[N],t[N];
    int n,m,k,i,a[N],cnt1,cnt2,cnt3,cnt;
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int cmp1(const event &a,const event &b)
    {
    	if(a.x==b.x) return a.val<b.val;
    	return a.x<b.x;
    }
    int cmp2(const event &a,const event &b)
    {
    	if(a.x==b.x) return a.val>b.val;
    	return a.x<b.x;
    }
    int cmp3(const event &a,const event &b)
    {
    	return (long double)a.val*b.f>(long double)b.val*a.f;
    }
    int cmp4(const event &a,const event &b)
    {
    	if(a.op==b.op) return a.id<b.id;
    	return a.op<b.op;
    }
    signed main()
    {
    	n=read();m=read();k=read();
    	for(i=1;i<=n;i++) a[i]=read();
    	for(i=1;i<=m;i++){
    		int op=read(),x=read(),val=read();
    		if(op==1) t1[++cnt1]=(event){op,i,x,val,1};
    		else if(op==2) t2[++cnt2]=(event){op,i,x,val,1};
    		else t3[++cnt3]=(event){op,i,x,val,1};
    	}
    	sort(t1+1,t1+cnt1+1,cmp1);
    	for(i=1;i<=cnt1;i++){
    		if(t1[i].x!=t1[i+1].x&&t1[i].val>a[t1[i].x]) t2[++cnt2]=(event){t1[i].op,t1[i].id,t1[i].x,t1[i].val-a[t1[i].x],1};
    	}
    	sort(t2+1,t2+cnt2+1,cmp2);
    	int tmp;
    	for(i=1;i<=cnt2;i++){
    		if(t2[i].x!=t2[i-1].x) tmp=a[t2[i].x];
    		tmp+=t2[i].val;
    		t3[++cnt3]=(event){t2[i].op,t2[i].id,t2[i].x,tmp,tmp-t2[i].val};
    	}
    	sort(t3+1,t3+cnt3+1,cmp3);
    	int cnt=min(cnt3,k);
    	for(i=1;i<=cnt;i++) t[i]=t3[i];
    	sort(t+1,t+cnt+1,cmp4);
    	printf("%lld
    ",cnt);
    	for(i=1;i<=cnt;i++) printf("%lld ",t[i].id);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    乐动力APP案例
    四则运算题目自动生成
    第0次作业
    CMDB整体项目梳理(1)
    cmdb项目准备
    DjangoAgain CBV与FBV
    Django ORM不完全操作
    Django 查漏补缺记录
    DjangoAgain_用小程序理解web框架
    DjangoAgain_url路由系统
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11876582.html
Copyright © 2020-2023  润新知