码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 6447(线段树+dp)

时间:2018-08-26 15:36:18      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:else   algo   线段树   scan   names   algorithm   mem   \n   note   

按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\n",ans);
    }
    return 0;
}

 

hdu 6447(线段树+dp)

标签:else   algo   线段树   scan   names   algorithm   mem   \n   note   

原文地址:https://www.cnblogs.com/Wangwanxiang/p/9537281.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!