hdu 6447(线段树+dp)

Posted wangwanxiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6447(线段树+dp)相关的知识,希望对你有一定的参考价值。

按y轴排序,y相同,按x排序,从下往上,从右往左dp(类似01背包),离散化一下x坐标,f[x]=max(f[x],f[1~x-1]+v[x][y]),用线段树查询一下1~x-1的最大值

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=1e5+100;
vector<int> hh[maxn];
int f[maxn];
int bb[maxn];
int maxi[maxn<<2];
void upnode(int p,int v,int l,int r,int rt)
{
    if(l==r)
    {
        maxi[rt]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) upnode(p,v,l,mid,rt<<1);
    if(p>mid) upnode(p,v,mid+1,r,rt<<1|1);
    maxi[rt]=max(maxi[rt<<1],maxi[rt<<1|1]);
}
int query(int L,int R,int l,int r,int rt)
{
     if(L<=l&&r<=R)
     {
         return maxi[rt];
     }
     int mid=(l+r)>>1;
     int zz=0;
     if(L<=mid) zz=max(zz,query(L,R,l,mid,rt<<1));
     if(R>mid) zz=max(zz,query(L,R,mid+1,r,rt<<1|1));
     return zz;
}
struct note
{
    int x,y;
    int w;
    bool operator <(const note &p) const
    {
        return y<p.y||y==p.y&&x<p.x;
    }
}aa[maxn];
int t;
int n;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(maxi,0,sizeof(maxi));
        scanf("%d",&n);
        int x,y,w;
        int ri=0;
        for(int i=1;i<=n;i++)
        {
            f[i]=0;
            bb[i]=0;
            hh[i].clear();
           scanf("%d%d%d",&x,&y,&w);
           if(x!=0&&y!=0)
           {
                ri++;
                aa[ri].x=x;
                aa[ri].y=y;
                aa[ri].w=w;
                bb[ri]=x;
           }
        }
        sort(aa+1,aa+1+ri);
        sort(bb+1,bb+1+ri);
        int ff=unique(bb+1,bb+1+ri)-(bb+1);
        int nn=bb[ff];
       int cnt=1;
       hh[1].push_back(1);
       aa[1].x=lower_bound(bb+1,bb+1+ff,aa[1].x)-bb;//离散化一下x
       for(int i=2;i<=ri;i++)
       {
          aa[i].x=lower_bound(bb+1,bb+1+ff,aa[i].x)-bb;
          if(aa[i].y==aa[i-1].y) hh[cnt].push_back(i);
          else
          {
              cnt++;
              hh[cnt].push_back(i);
          }
       }
       memset(f,0,sizeof(f));
       int ans=0;
       for(int j=hh[1].size()-1;j>=0;j--)
       {
           int k=hh[1][j];
           upnode(aa[k].x,aa[k].w,1,nn,1);
           f[aa[k].x]=aa[k].w;
           if(f[aa[k].x]>ans) ans=f[aa[k].x];
       }
       for(int i=2;i<=cnt;i++)
       {
           for(int j=hh[i].size()-1;j>=0;j--)//倒着搜,f[1~x-1]正好是前面那一行的值(即小于当前y的那一行),还能保证x小于当前x
           {
              int k=hh[i][j];
              if(aa[k].x-1>=1)
              {
                   f[aa[k].x]=max(f[aa[k].x],query(1,aa[k].x-1,1,nn,1)+aa[k].w);//线段树查询1~x-1的最大值
                   upnode(aa[k].x,f[aa[k].x],1,nn,1);
              }
              else
              {
                  f[aa[k].x]=max(f[aa[k].x],aa[k].w);//x坐标是离散化后的1时无法搜索1~x-1,所以更新一下
                  upnode(aa[k].x,f[aa[k].x],1,nn,1);
              }
              if(f[aa[k].x]>ans) ans=f[aa[k].x];
           }
       }
       printf("%d
",ans);
    }
    return 0;
}

 

以上是关于hdu 6447(线段树+dp)的主要内容,如果未能解决你的问题,请参考以下文章

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

HDU 6447

HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP

HDU 4521 小明系列问题——小明序列 (线段树维护DP)

HDU 6447 - YJJ's Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]

HDU 6447 YJJ’s Salesman (树状数组 + DP + 离散)