Codeforces Round #521 D Shop 堆

题目大意:给定k个数,n个操作,每个操作有三种类型:

1.a[i]=b

2.a[i]+=b

3.a[i]*=b

其中i和b是操作指定的

现在你可以进行最多m次操作,每个操作最多进行一次,要求操作结束后所有数的乘积最大

按使用的顺序输出每个操作的编号

乱七八糟地写了一发D……结果最后没调出来QAQ B题也没写 到最后就写了A和C 排了100+。。。

首先对于同一个数我们执行的所有操作一定是按照1-2-3的顺序

操作1最多执行1次 因此我们不妨将每个数的操作1取最大后当做操作2处理

现在就只剩下了两个操作 2和3

3操作的影响是答案*=b

2操作的影响是答案*=(a[i]+b)/a[i]

但是a[i]是会变化的,因此不能直接贪心

我们发现2操作虽然彼此独立 但是在操作数为m的限制下 显然对于每个数 2操作的顺序按照从大大小取是更优的

因此我们不妨将每个数所有的2操作都排个序,将最大的加入堆

然后每次取出堆顶 如果这个堆顶是操作2 就取出这个数的下一个操作2并计算本次的(a[i]+b)/a[i]

最后将所有操作按照type排个序即可

时间复杂度O(mlogn)

注意a[i]可能会加爆

#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
#define EPS 1e-9
using namespace std;
int k,n,m;
int a[M],to_modify[M];
long long _a[M];
struct abcd{
    int type,i,b;
}b[M];
vector<pair<double,int> > modifictions[M];
priority_queue<pair<double,int> > heap;
int stack[M],top;
bool Compare(int x,int y)
{
    return b[x].type < b[y].type;
}
int main()
{
	//freopen("fuck.txt","r",stdin);
    int i;
    cin>>k>>n>>m;
    for(i=1;i<=k;i++)
        scanf("%d",&a[i]),_a[i]=a[i];
    for(i=1;i<=n;i++)
    {
        scanf("%d%d%d",&b[i].type,&b[i].i,&b[i].b);
        if(b[i].type==1)
        {
            if(!to_modify[b[i].i]||b[to_modify[b[i].i]].b<b[i].b)
                to_modify[b[i].i]=i;
        }
        else if(b[i].type==2)
            modifictions[b[i].i].push_back(make_pair(b[i].b,i) );
        else
            heap.push(   pair<double,int>(log(b[i].b),i)    );
    }
	for(i=1;i<=k;i++)
        if(to_modify[i]&&b[to_modify[i]].b>a[i])
            modifictions[i].push_back(     pair<double,int>(b[to_modify[i]].b-a[i],to_modify[i])     );
    for(i=1;i<=k;i++)
       	if(modifictions[i].size())
    	{
    		sort(modifictions[i].begin(),modifictions[i].end());
    		pair<double,int> temp=modifictions[i].back();modifictions[i].pop_back();
    		temp.first=log(a[b[temp.second].i]+temp.first)-log(a[b[temp.second].i]);
			heap.push(temp);
    	}

    for(i=1;i<=m&&heap.size();i++)
    {
 		pair<double,int> temp=heap.top();heap.pop();
        stack[++top]=temp.second;
        if( b[temp.second].type==1 )
            _a[b[temp.second].i]+=b[temp.second].b-a[b[temp.second].i];
        else if( b[temp.second].type==2 )
            _a[b[temp.second].i]+=b[temp.second].b;
        else
        	continue;
        if(modifictions[b[temp.second].i].size())
        {
			pair<double,int> _temp=modifictions[b[temp.second].i].back();
			modifictions[b[temp.second].i].pop_back();
			_temp.first=log(_a[b[temp.second].i]+_temp.first)-log(_a[b[temp.second].i]);
			heap.push(_temp);
		}
    }
    sort(stack+1,stack+top+1,Compare);

    cout<<top<<endl;
    for(i=1;i<=top;i++)
        printf("%d%c",stack[i],i==top?'\n':' ');
}
时间: 2024-10-13 06:52:56

Codeforces Round #521 D Shop 堆的相关文章

Codeforces Round #521 (Div. 3) D. Cutting Out 【二分+排序】

任意门:http://codeforces.com/contest/1077/problem/D D. Cutting Out time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output You are given an array ss consisting of nn integers. You have to find any ar

Codeforces Round #521 (Div. 3)

题目链接:http://codeforces.com/contest/1077 A.Frog Jumping 解题思路: AC代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 LL T,a,b,k;///差值相减即可 5 int main(){ 6 while(cin>>T){ 7 while(T--){ 8 cin>>a>>b>>k; 9

CodeForces Round #521 (Div.3) C. Good Array

http://codeforces.com/contest/1077/problem/C Let's call an array good if there is an element in the array that equals to the sum of all other elements. For example, the array a=[1,3,3,7]a=[1,3,3,7] is good because there is the element a4=7a4=7 which

Codeforces Round #521 (Div. 3) D. Cutting Out

D. Cutting Out 题目链接:https://codeforces.com/contest/1077/problem/D 题意: 给你n个数,现在要你选k个数出来,并且能够从这n个数种选取尽量多的这k个数. 题解: 一开始想的贪心+模拟,然后写崩了... 其实这个题二分一下选几组就好了,因为要选几个数是固定了的,所以我们可以用二分来判断可行性(根据二分的x和每个数出现的次数来判断),即是否可以选够k个数,这个很容易办到. 然后最后统计一下每个数出现的个数,最后无脑选输出答案就行了. 代

【Codeforces Round 521】Codeforces #295(div. 1)

521A DNA Alignment 题意:给一个字符串\(s\),求有多少个\(t\)使得\(\rho(s,t)\)最大. 其中,\(t\)是一个和\(s\)等长的串, \(\rho(s,t)=\max_{i=0}^{n-1}\max_{j=0}^{n-1}h(shift(s,i),shift(t,i))\) \(h(s,t)=\sum_{i=0}^ns_i\ne t_i\) \(shift(s,i)=s_{i+1\dots n}+s_{1\dots i}\) 思路:首先我们看最大的答案是多少

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除

Codeforces Round #399 B 思维 C 模拟 D 概率dp E SG博弈

Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)B. Code For 1 题意:数n,不断拆分为 n/2, n&1, n/2,直到都为0或1.求区间[l, r]有多少个1. tags:画一画很容易看出来,类似dfs中序遍历. //#399 B #include<bits/stdc++.h> using namespace std; #pragma comment(linker, &quo

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

Codeforces Round #256 (Div. 2/C)/Codeforces448C_Painting Fence(分治)

解题报告 给篱笆上色,要求步骤最少,篱笆怎么上色应该懂吧,,,刷子可以在横着和竖着刷,不能跳着刷,,, 如果是竖着刷,应当是篱笆的条数,横着刷的话,就是刷完最短木板的长度,再接着考虑没有刷的木板,,, 递归调用,,, #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define inf 999999999999999 using namespace