HDU6447 YJJ's Salesman 2018CCPC网络赛 树状数组+离散化

比赛的时候,一开始写了个二维最朴素的dp,果断TLE。。然后就不知道怎么优化了。。。比完赛听某大佬学长说,先离散化,再树状数组维护一下y坐标,降维成一维的dp。

之前一直没学过离散化和树状数组,现在看来得学了QAQ...附上讲解博客Orz:

离散化:https://blog.csdn.net/xiangaccepted/article/details/73276826 

树状数组:https://www.cnblogs.com/acgoto/p/8583952.html

具体思路就不说了,直接上AC代码吧:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAX=1e5+5;
int n;
struct point
{
    int x,y;
    int val;
    int id;
}p[MAX];
int tmp[MAX];
int dp[MAX];

int c[MAX];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int val)
{
    while(x<=n)
    {
        c[x]=max(c[x],val);
        x+=lowbit(x);
    }
}
int quary(int x)
{
    int ans=0;
    while(x>0)
    {
        ans=max(ans,c[x]);
        x-=lowbit(x);
    }
    return ans;
}
bool cmp(struct point a,struct point b)
{
    if(a.x==b.x)
        return a.y<b.y;
    else
        return a.x<b.x;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(p,0,sizeof(p));
        memset(tmp,0,sizeof(tmp));
        memset(dp,0,sizeof(dp));
        memset(c,0,sizeof(c));//注意清空
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].val);
            tmp[i]=p[i].y;
        }

        //离散化
        sort(tmp+1,tmp+1+n);
        int tol=unique(tmp+1,tmp+1+n)-tmp-1;
        for(int i=1;i<=n;i++)
            p[i].y=lower_bound(tmp+1,tmp+1+tol,p[i].y)-tmp;

        sort(p+1,p+1+n,cmp);
        int ans=0,pos=1;
        for(int i=1;i<=n;i++)
        {
			while(pos<i&&p[pos].x<p[i].x)//注意必须有判断小于x的条件
			{
				update(p[pos].y,dp[pos]);
				pos++;
			}
            dp[i]=quary(p[i].y-1)+p[i].val;
            ans=max(ans,dp[i]);
        }
        printf("%d\n",ans);
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/82148347