2018CCPC网络赛-线段树求区间最值+离散化+dp

转自:HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp

Problem:Portal传送门

 原题目描述在最下面。
 1e5个点,问从(0,0)走到(1e9,1e9)的最大收益。
 当你从(u-1,v-1)走到(u,v)时,你可以获得点(u,v)的权值。

solution:

这里写图片描述
 十分详细了。
 直接线段树区间最值。当然也可以树状数组,不能st表。
 dp[i]=max(query_max(0,dp[i]−1,1)+val[i],dp[i])dp[i]=max(query_max(0,dp[i]−1,1)+val[i],dp[i])
 update(i,dp[i],1)update(i,dp[i],1)
 记得离散化再排序,先x从小到大,再y从大到小,每次更行一行。
 按01背包的更新顺序,滚动数组优化为一维。
 细节见代码。

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef unsigned long long LL;
const int N = 2e5 + 7;
const int M = 1e5 + 7;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int ar[N],br[N];//离散化
int dp[N];
struct lh //储存1e5个点
{
    int x,y,v;
} op[N];
bool cmp(lh &a,lh &b)
{
    if(a.x!=b.x)return a.x<b.x;
    return a.y>b.y;
}
int n;
/**********线段树区间最值**********/
struct lp
{
    int l, r, sum;
} cw[N<<2];
void push_up(int rt)
{
    cw[rt].sum = max(cw[lson].sum, cw[rson].sum);
}
void build(int l,int r,int rt)
{
    cw[rt].l = l;
    cw[rt].r = r;
    cw[rt].sum = 0;
    if(l==r)
    {
        return;
    }
    int m = (l+r)/2;
    build(l,m,lson);
    build(m+1,r,rson);
    push_up(rt);
}
void update(int p,int c,int rt)
{
    int l = cw[rt].l;
    int r = cw[rt].r;
    int m = (l+r)/2;
    if(l==r)
    {
        cw[rt].sum = c;
        return;
    }
    if(p<=m)update(p,c,lson);
    else update(p,c,rson);
    push_up(rt);
}
int query(int L,int R,int rt)
{
    int l = cw[rt].l;
    int r = cw[rt].r;
    int m = (l+r)/2;
    if(L<=l&&r<=R)
    {
        return cw[rt].sum;
    }
    if(L>m)return query(L,R,rson);
    else if(R<=m)return query(L,R,lson);
    return max(query(L,m,lson),query(m+1,R,rson));
}
/****************/
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%d%d%d",&op[i].x,&op[i].y,&op[i].v);
            ar[i] = op[i].x;
            br[i]=op[i].y;
        }
        int p = n + 1;
        ar[n] = 0;
        br[n] = 0;
        sort(ar,ar+p);
        sort(br,br+p);
        int a = unique(ar,ar+p)-ar;
        int b = unique(br,br+p)-br;
        for(int i = 0; i < n; ++i)
        {
            op[i].x=lower_bound(ar,ar+a,op[i].x)-ar;
            op[i].y=lower_bound(br,br+b,op[i].y)-br;
        }
        //以上离散化
        sort(op,op+n,cmp);
        build(0, b, 1);
        mme(dp, 0);
        for(int i = 0; i < n; ++i)
        {
            int flag = op[i].x, j;
            for(j = i; j < n; ++j)
            {
                if(op[j].x != flag)
                {
                    break;
                }
                int tmp = query(0, op[j].y-1, 1) + op[j].v;
                if(tmp > dp[op[j].y])
                {
                    dp[op[j].y] = tmp;
                    update(op[j].y, dp[op[j].y], 1);
                }
            }
            i = j - 1;
        }
        int ans = 0;
        for(int i = 0; i <= b; ++i)
        {
            ans = max(ans, dp[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/flyzer/article/details/82936442
今日推荐