首页 > 其他分享 >Prefix Purchase 题解

Prefix Purchase 题解

时间:2023-12-19 12:26:05浏览次数:34  
标签:Purchase int 题解 mn cin Prefix ans 字典 define

题意

给定一个长度为 \(n\) 的序列 \(ans\),初始值全部为 \(0\)。你一共有 \(k\) 个硬币,你可以选择花 \(a_{i}\) 个硬币来使 \(ans_{1}\) 到 \(ans_{i}\) 中的所有数加一。求最终能得到的 \(ans\) 序列中字典序最大的一个。

思路

首先我们可以发现一个很显然的性质:如果满足 \(a_{i}>a_{i+1}\) 的话,那么选 \(i+1\) 位置一定比选 \(i\) 位置更优。所以我们就可以先将 \(a_{i}\) 赋值为 \(\min(a_{i},a_{i+1})\),这样就可以避免掉上面所说的这种情况了。

又因为题目要求最终序列的字典序最大(靠前的数字最大),所以我们肯定要贪心的去先选前面的,即从 \(a_{1}\) 开始选。但是我们会发现选完 \(a_{1}\) 之后 \(k\) 还会剩下一些,如果直接不管的话肯定不是最优的。所以我们就可以用 \(k\) 剩下的这些值去将一些选 \(a_{1}\) 的变成选 \(a_{2}\) 的,且个数不变,这样既可以保证当前的字典序不变(选 \(1\) 的个数没变),还可以让后面的字典序变大(选 \(2\) 的个数变多)。那么这样操作一定是更优的。那么就可以算出选 \(a_{2}\) 的数量就应该是:\((k-k \div a_{1} \times a_{1}) \div (a_{2}-a_{1})\)。意思是用 \(k\) 剩下的值除以每一次变化需要的代价。然后对于每一个 \(a_{i}\) 都进行这样的操作就可以了。

但是这里有几个点需要注意:

  • 因为除数不能为 \(0\),所以当 \(a_{i}=a_{i+1}\) 时,直接将 \(ans_{i}\) 赋值为 \(ans_{i-1}\) 就可以了。

  • 根据题目定义,显然 \(ans_{i+1}\) 不可能大于 \(ans_{i}\),所以操作的时候还需要特判一下。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f
#define inf_db 127
#define ls id << 1
#define rs id << 1 | 1
#define re register
#define endl '\n'
typedef pair <int,int> pii;
const int MAXN = 2e5 + 10;
int T,n,k,mn = 1e18,a[MAXN],ans[MAXN];
signed main()
{
	cin >> T;
	while(T--)
	{
		cin >> n;
		mn = ans[0] = 1e18;
		for(int i = 1;i <= n;i++) cin >> a[i];
		for(int i = n;i >= 1;i--) mn = min(mn,a[i]),a[i] = mn; 
		cin >> k;
		for(int i = 1;i <= n;i++)
		{
			if(a[i] - a[i - 1] == 0) ans[i] = ans[i - 1];
			else ans[i] = min(k / (a[i] - a[i - 1]),ans[i - 1]);
			cout << ans[i] << " ";
			k -= (a[i] - a[i - 1]) * ans[i];
		}
		cout << endl;
		for(int i = 1;i <= n;i++) ans[i] = 0;
	}
	return 0;
} 

标签:Purchase,int,题解,mn,cin,Prefix,ans,字典,define
From: https://www.cnblogs.com/Creeperl/p/17913427.html

相关文章

  • Sum of XOR Functions 题解
    题意给定一个数\(n\)和一个包含\(n\)个数的序列\(a\),求出以下式子模\(998244353\)的值:\(\sum_{i=1}^{n}\sum_{j=i}^{n}f(i,j)\times(j-i+1)\)。其中\(f(i,j)\)的值为\(a_{i}\oplusa_{i+1}\oplusa_{i+2}\oplus...\oplusa_{j}\)。思路首先我们可以考虑这道题的......
  • Candy Party (Hard Version) 题解
    原题链接:CF1868B2,简单版:CF1868B1。题意有\(n\)个人,第\(i\)个人手上最初有\(a_{i}\)颗糖。现在每个人可以把自己手中的糖选一些给不多于一个人,同时每个人也只能接受不多于一个人的糖,选出的糖的数量必须是二的次幂。问能否能让每个人最终手上的糖的数量相等。思路首先,这......
  • 【0909 B组】切蛋糕 题解
    原题链接:切蛋糕。题意给定一个\(n\)行\(m\)列的蛋糕,问横着切\(i\)刀,竖着切\(j\)刀后美味度最小的蛋糕的美味度尽可能大。一块蛋糕的美味度为它所含有的小块的美味度之和。数据范围:\(1\len,m\le14\)。思路看到数据范围,我们可以考虑一种类似于状态压缩的思想,先枚举......
  • Cyclic Operations 题解
    前言看这道题有好多巨佬都是用Tarjan来做的,在这里讲一个自认为比较简单的做法,(不到\(30\)行)。题意题意比较难讲,建议自己去看一下翻译,在这里不多赘述。思路首先看到题目中间给的一个每一次操作的式子:\(a_{l_{i}}=l_{(i\modk)+1}\)。仔细观察这个式子后会发现,其实每一次......
  • P4630 [APIO2018] 铁人两项 题解
    今天学习了圆方树,并且做了一道和这道题很像的题,于是就又来做了一下这道题。题意给定一张不保证连通的无向图。求有多少个点对\((a,b,c)\)满足\(a\)到\(c\)的简单路径上经过了点\(b\)。思路显然圆方树。点双缩点过后构造一颗圆方树,然后考虑如何计算答案。圆方树有一个实......
  • [ABC315G] Ai + Bj + Ck = X (1 <= i, j, k <= N) 题解
    原题链接:ABC315G前置知识:扩展欧几里得算法。如果还不会扩欧的话,建议先去做这道题。题意给定\(n,a,b,c,k\)。求有多少个\(x,y,z(x,y,z\len)\)满足\(ax+by+cz=k\)。思路首先看到题目给出的方程式:\(ax+by+cz=k\)。我们会发现很像扩欧板子中的:\(ax+by=k\)。只不过又多了一......
  • [ABC318G] Typical Path Problem 题解
    原题链接:ABC318G显然是圆方树。点双缩点过后建立一颗以点\(c\)为根节点的圆方树,考虑什么情况是合法的。从点\(a\)开始往上跳直到跳到点\(c\),如果中间走过了某一个方点并且这个方点与\(b\)点有直接连边,那么就是合法的;否则不合法。证明:如果路径中所经过的方点和\(b\)点......
  • [ABC318F] Octopus 题解
    前言赛时只做到了E题,赛后才来补的F题,还没做出来,看来还是我太菜了。看了题解过后感觉这道题的思路特别巧妙,于是就来写了这篇题解。题意简述一下题意。有\(n\)个宝藏位置分别在\(a_{i}\),另外有一只章鱼有\(n\)条触手,每条触手的长度为\(b_{i}\)。求有多少个点\(k\)......
  • Two-Colored Dominoes 题解
    前言看了这道题的几篇题解,感觉讲的方法都比较麻烦,这里讲一个感觉比较简单的方法。思路首先判断是否有解。计算一下每一行和每一列的牌的数量,只要有一个是奇数就无解,否则有解。证明显然,偶数一定可以分成两组,在纸上模拟一下也可以得出。其次看如何构造。对于竖着的牌,显然只对每......
  • P3071 [USACO13JAN] Seating G 题解
    题意:维护两个操作,区间推平,求连续\(0\)的个数为\(x\)的最前位置。线段树。因为需要求连续\(0\)的个数,所以维护区间左边连续\(0\)的最大个数,区间右边连续\(0\)的最大个数以及区间连续\(0\)的最大个数。注意修改的时候要看是修改为\(1\)还是修改为\(0\)。查询的时......