思维杂题

思维杂题

Buy Low Sell High

最简单的贪心:买入最小的股票 在可以盈利的当天卖出

那么这个在递减数据下是正确的 但是在递增数据下显然是错的 如 \(1\ 2\ 100\)

如果贪心 我们只会在 \(1\) 节点买入并在 \(2\) 节点卖出 获得 \(1\) 的贡献

但是实际上我们可以将 \(1\) 股票在 \(100\) 的时候卖出来获得更多贡献

那么我们考虑反悔贪心:

如果买了 因为是用小根堆贪心 就是一定最优的 直接出队

我们对于第 \(i\) 天买到第 \(j\) 天卖的操作 价值为 \(v_j-v_i\)

那么我们现在要实现反悔操作 就需要入队一个值 \(val\) 使得如果第 \(i\) 天买到第 \(k\) 天卖 价值更优

相当于是答案要加上 \(v_k-val+(v_j-v_i)=v_k-v_i\) 解得 \(val=a_j\) 所以如果我们可以卖 那么需要多推入队列中一个数来实现反悔

反悔之后 \(j\) 点从 \(2\) 个变成 \(1\) 个 显然 \(j\) 点相当于空出来了 可以进行下一次操作 符合我们的设计

相当于是用每个点在队列内部的数量来表示该点的状态

\(0\) 个为买了 \(1\) 个为不操作 \(2\) 个为卖了

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long

int read ()
{
	int x = 0 , f = 1;
	char ch = cin.get();
	while ( !isdigit ( ch ) ) { if ( ch == '-' ) f = -1; ch = cin.get(); }
	while ( isdigit ( ch ) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = cin.get(); }
	return x * f;
}
int n , ans;

priority_queue < int,vector<int>,greater<int> > q;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 ; i <= n ; i ++ )
	{
		int x = read();
		if ( !q.empty() && q.top() < x ) ans += x - q.top() , q.pop() , q.push(x);
		q.push(x);
	}
	cout << ans << endl;
	return 0;
}

P4552 [Poetize6] IncDec Sequence

考虑差分数组

显然查分数组有正有负 那么最优操作应该将一个正数减掉 \(1\) 再将一个负数加上 \(1\) 这样一次能操作两个 是最优情况

那么最小操作次数就是正数和负数中间的最大值

结果数即为所有单独修改一个的操作+1 (因为可以将前面的往上加 也可以将后面的往下减)

#include <bits/stdc++.h>
using namespace std;
#define inl inline
#define int long long
const int N = 1e6 + 5;

inl int read ()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit ( ch ) ) { if ( ch == '-' ) f = -1; ch = getchar (); }
	while ( isdigit ( ch ) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar (); }
	return x * f;
}

int n , a[N] , zheng , fu , cha[N];

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	a[1] = read();
	for ( int i = 2 ; i <= n ; i ++ )
	{
		a[i] = read() , cha[i] = a[i] - a[i-1];
		if ( cha[i] > 0 ) zheng += cha[i];
		else fu += ( - cha[i] );
	}
	// for ( int i = 1 ; i <= n ; i ++ ) cout << cha[i] << ' ';
	// cout << endl;
	cout << max ( zheng , fu ) << endl;
	cout << abs ( zheng - fu ) + 1 << endl;
	return 0;
} 
posted @ 2023-10-08 06:24  Echo_Long  阅读(5)  评论(0编辑  收藏  举报