1001Buy and Resell 某种东西在不同的时间有不同的价格,允许在任意时刻买入,并在之后的任意时刻卖出,求所能获得的最大的收益。
考虑如果是在第k天卖出的话,要使收益最大必然是在前面k-1天中空闲的时间里价格最低的一天买入的。
如果某次买入的价格和前面某次交易的卖出价格相同的话,那么就将这两次交易合并成一次,因为题目有在收益最大的条件下交易次数最少的要求。
把每一天拆成两个点, 卖出和买入。使用优先队列实现以下操作:
从前到后每次将这一天的两个点压入优先队列中,如果队列顶端和这次放入的元素不同,就说明在他前面存在比他低的价格,尝试对它进行匹配。如果这个价格尚未被当做卖出价匹配过,就正常匹配,交易数增加1。这个价格已经作为卖出价格出现过,就要和前面的那次操作合并起来。这系列操作结束后,队列顶端的元素,要么是这一次里被匹配了,要么是这一次压进去的元素没有被当成卖出价匹配,这两种情况,都需要将队顶弹出。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200010;
const ll INF = (1LL<<62) - 1;
const ll mod = 100000007;
int t, n, a, num;
priority_queue<int>q;
map<int, int>mp;
ll ans;
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
while(!q.empty()) q.pop();
mp.clear();
ans = 0, num = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d", &a);
q.push(-a), q.push(-a);
int u = q.top();
if(u != -a)
{
if(!mp[u]) num += 2;
else mp[u]--;
mp[-a]++;
ans += 1LL*(u + a);
}
q.pop();
}
printf("%I64d %d\n", ans, num);
}
return 0;
}
1010YJJ's Salesman 在地图上某些点有权值,从(0,0)出发每次只能向右向下和向右下,但是只有从左上方过来时才能得到权值。求所能得到的最大权值。
将村庄按照二维偏序排序,先按x升序,x相同时按y降序。设dp[i]表示前i个点所获得的最大权值,那么就有dp[i] = max(dp[j] + e[i].w),其中j点严格小于i点。这个过程用树状数组来维护,就是一个区间最大值的问题。显然坐标要离散化。
真的
骚
想不出
orz
dp没救了
dp只会树上dp一下这样子
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200050;
const ll INF = (1LL<<62) - 1;
const ll mod = 100000007;
int t, n, no;
int num[maxn], dp[maxn];
struct node
{
int x, y;
int w;
bool operator < (const node& a) const
{
if(x == a.x) return y > a.y;
return x < a.x;
}
}e[maxn];
int lowbit(int x) {return x & (-x);}
int query(int x)
{
int ans = 0;
while(x)
{
ans = max(ans, dp[x]);
x -= lowbit(x);
}
return ans;
}
void update(int x, int v)
{
while(x < maxn)
{
dp[x] = max(dp[x], v);
x += lowbit(x);
}
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
no = 0;
memset(dp, 0, sizeof(dp));
for(int i = 0;i < n;i++)
{
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].w);
num[no++] = e[i].x;
num[no++] = e[i].y;
}
sort(num, num + no);
for(int i = 0;i < n;i++)
{
e[i].x = lower_bound(num, num + no, e[i].x) - num + 1;
e[i].y = lower_bound(num, num + no, e[i].y) - num + 1;
}
sort(e, e + n);
for(int i = 0;i < n;i++)
{
int tp = query(e[i].y - 1) + e[i].w;
update(e[i].y, tp);
}
int ans = query(no + 1);
printf("%d\n", ans);
}
return 0;
}