http://codeforces.com/problemset/problem/865/D
http://acm.hdu.edu.cn/showproblem.php?pid=6438
题意略
每一系列交易其实就是一条链 一次完整交易肯定有买有卖 链头链尾就是买入和卖出的日子 中间元素只是中转作用 就像(-1+2)+(-2+3)这样 2只是达成最优交易的一个过度 我们只关心链头链尾 具体体现就是 堆中只维护链尾 链头永远剔除出堆不会再用(因为不能空手套白狼)
在堆中 val为价值 flag标志是否为链头 在cf 865d种只需贪心的考虑 肯定要使赚取的差价尽可能大 所以在所有交易链中挑一个链尾val值最小的 然后看是不是链头 是链头就彻底去掉了
但是在hdu 6438中 还需额外考虑使交易次数最少 其实就是使利益最大化的前提下交易链的条数最少 在堆中当两元素价值一样时 让非链头元素在上即可
cf 865d
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
struct node
{
ll val;
int flag;
bool friend operator < (node n1,node n2){
return n1.val>n2.val;
}
};
priority_queue <node> que;
ll ary[maxn];
int n;
int main()
{
node cur,tmp;
ll ans;
int t,i;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lld",&ary[i]);
}
while(!que.empty()) que.pop();
tmp.val=ary[1],tmp.flag=0;
que.push(tmp);
ans=0;
for(i=2;i<=n;i++){
cur=que.top();
tmp.val=ary[i],tmp.flag=0;
if(ary[i]>cur.val){
que.pop();
ans+=ary[i]-cur.val;
if(cur.flag){
cur.flag=0;
que.push(cur);
}
tmp.flag=1;
}
que.push(tmp);
}
printf("%lld\n",ans);
return 0;
}
hdu 6438
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node
{
ll val;
int flag;
bool friend operator < (node n1,node n2){
if(n1.val==n2.val) return n1.flag<n2.flag;
else return n1.val>n2.val;
}
};
priority_queue <node> que;
ll ary[maxn];
int n;
int main()
{
node cur,tmp;
ll ans1;
int t,ans2,i;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lld",&ary[i]);
}
while(!que.empty()) que.pop();
tmp.val=ary[1],tmp.flag=0;
que.push(tmp);
ans1=0,ans2=0;
for(i=2;i<=n;i++){
cur=que.top();
tmp.val=ary[i],tmp.flag=0;
if(ary[i]>cur.val){
que.pop();
ans1+=ary[i]-cur.val;
if(cur.flag){
cur.flag=0;
que.push(cur);
}
else ans2++;
tmp.flag=1;
}
que.push(tmp);
}
printf("%lld %d\n",ans1,2*ans2);
}
return 0;
}