贪心/妙妙题单(三)(中等-困难)
CF 865D D. Buy Low Sell High
tag: 反悔贪心,贪心,妙妙题
建一个最小堆,从前往后按照顺序,对每个值判断:
-
如果当前值比堆顶值还小,则直接放入堆中(注意放入堆中不是买)
-
如果当前值比堆顶值大,则把堆顶弹出(在当前为止卖掉)。会有一种情况,在当前为止卖掉不如留到之后再卖。
对于情况二,设堆顶值,当前值,之后的更优值分别为 \(p_1,p_2,p_3\)
则如果现在卖掉,且再以现在的价格买入一个,留到 \(p_3\) 卖掉:\((p_3-P_2)+(p_2-p_1)\)
和直接把 \(p_1\) 留到 \(p_3\) 卖一样。所以,在情况 2 的弹出堆顶后,可以再插入一个 \(p_2\)。注意,这个 \(p_2\) 不是情况 \(1\) 的 \(p_2\),所以这里需要插入两个 \(p_2\)
虽然插入两个,但是和题意不冲突,因为第一个 \(p_2\) 实质上是一个虚拟的东西
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
int ans=0;
priority_queue<int,vector<int>,greater<int>> q;
for(int i=1;i<=n;i++){
int val;
cin>>val;
if(q.size() && val>q.top()){
ans+=val-q.top();
q.pop();
q.push(val);
}
q.push(val);
}
cout<<ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
}
CF 1110E Magic Stones
首先判断第一个数和最后一个数是否一样
将数组写成差分的形式:
\(a:\) \(a1,~~a1+d2,~~a1+d2+d3,~~a1+d2+d3+d4,~~...~~,~~a1+d1+d2+...+dn\)
会发现,对于 \(d\) 数组 \(d2-dn\) 而言,操作一次等价于交换 \(d\) 数组中某些位置的顺序
所以,如果 \(a,b\) 两个数组的 \(d\),排序后完全相同,则可以变过去
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<int> a(n+1),b(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int j=1;j<=n;j++){
cin>>b[j];
}
if(a[1]!=b[1] || a[n]!=b[n]){
cout<<"No\n";
return;
}
vector<int> d1,d2;
for(int i=2;i<=n;i++){
d1.push_back(a[i]-a[i-1]);
d2.push_back(b[i]-b[i-1]);
}
sort(d1.begin(),d1.end());
sort(d2.begin(),d2.end());
for(int i=0;i<d1.size();i++){
if(d1[i]!=d2[i]){
cout<<"No\n";
return;
}
}
cout<<"Yes\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
}
CF 1473C Array Destruction
注意到每次选两个数的时候,必须有当前最大值
所以,初始时一个数固定是最大值,\(O(n)\) 的枚举另一个数即可
总复杂度 \(O(n^2)\)
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<int> a(2*n+1);
multiset<int> st;
for(int i=1;i<=2*n;i++){
cin>>a[i];
st.insert(a[i]);
}
sort(a.begin()+1,a.end());
for(int i=1;i<2*n;i++){
auto t=st;
t.erase(t.find(a[2*n]));
t.erase(t.find(a[i]));
int x=a[2*n];
vector<pii> ans;
ans.push_back({a[2*n],a[i]});
bool f=1;
while(t.size()){
int mx=*t.rbegin();
t.erase(t.find(mx));
int nd=x-mx;
if(t.count(nd)){
x=mx;
ans.push_back({mx,nd});
t.erase(t.find(nd));
}
else{
f=0;
break;
}
}
if(f==0) continue;
cout<<"YES\n";
cout<<ans[0].first+ans[0].second<<endl;
for(auto [x,y]:ans){
cout<<x<<" "<<y<<endl;
}
return;
}
cout<<"NO\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}

浙公网安备 33010602011771号