T1
题目描述:
洪蛤吨来到了一条有NN家商店的步行街,商店从左往右依次从11标号到NN。每家商店都买卖同一件产品,且都有同样的规矩:每个来到店里的人,只能买一件产品,卖一件产品,或者什么都不做。有趣的是,在同一家店里买卖产品,支出或者收到的钱是一样的。具体的,如果洪蛤吨在第ii家店里买/卖一件产品,那么洪蛤吨将会支出/收到AiAi单位的货币。
洪蛤吨将从11号商店依次走到NN号商店,一开始洪蛤吨有无限的初始资金,但并没有任何一件产品。
洪蛤吨想知道,当他完成这次步行的时候,他的收益最大是多少。在此前提下,洪蛤吨还希望进入店内买/卖产品的次数尽量少。
输入格式
第一行一个整数TT,表示数据组数
对于每组数据,第一行一个整数NN,接下来一行NN个整数,第ii个整数表示AiAi。
输出格式
对于每组数据,输出一行两个整数表示最大收益和在满足最大收益的前提下的最小交易次数,请注意,答案可能会很大。
样例输入
2
3
1 2 3
3
3 2 1
样例输出
2 2
0 0
数据规模
对于 15%15% 的数据,N≤10N≤10。
对于 25%25% 的数据,N≤16N≤16。
对于 45%45% 的数据,N≤200N≤200。
![](/qrcode.jpg)
对于 70%70% 的数据,N≤2000N≤2000。
对于 100%100% 的数据, 1≤T≤51≤T≤5,1≤N≤500001≤N≤50000,1≤Ai≤1091≤Ai≤109。
题目信息
题目类型:传统型
输入文件:标准输入
输出文件:标准输出
时间限制:1 s
空间限制:512 MB
题解:这道题,一开始我们猜了一个错误的结论,然后用线段树维护了半天,最后还暴零了,水啊水啊
一开始猜的结论是这样的,最大的肯定和最小的匹配才对,但并非如此,我们来看这个,
1 4 2 9 若用最大与最小匹配,那么答案为,8 但是,其实答案为10,。。。
怎么解决这种问题呢,我们可以用一个优先级队列来维护,并且维护这个点是否用过,若用过,但遇到更优
情况,我们就用ans+=(a[i]-Q.frist)但是交换次数不加,就相当于我们可以反悔,若遇到最优解,所以在把,
被反悔的值加回队列里面去就行了,
总结:以后写题,还是要先写暴力,既可以保证最后不出锅,也可以验证自己结论的正确性,这次考试给自己一个深刻的教训啊
代码:
#include<cstdio> #include<algorithm> #include<queue> using namespace std; struct my{ int v,d; bool operator<(const my &rhs)const{ if(rhs.v==v) return d>rhs.d; return v>rhs.v; } }; const int maxn=100000+10; priority_queue<my>Q; int a[maxn]; int main(){ int t; scanf("%d",&t); while(t--){ while(!Q.empty()) Q.pop(); int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); long long ans=0; int num=0; my u; u.v=a[1]; u.d=1; Q.push(u); for (int i=2;i<=n;i++){ u=Q.top(); if(a[i]>u.v){ Q.pop(); ans+=(a[i]-u.v); num+=u.d; if(u.d==0) Q.push((my){u.v,1}); Q.push((my){a[i],0}); } else { Q.push((my){a[i],1}); } } printf("%lld %d\n",ans,num*2); } return 0; }