2018 CCPC 网络赛 补题

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;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/82056643