pku3277 horizon

首先,看到这题就感觉亮瞎,好像没有任何突破口,因为以前做过一个矩阵求并的问题,那个题目还是比较难的,但是这道题目和hdu1225所不同的地方在于,他的所有矩阵y1坐标都是0,也就是说建筑物都是落地的,不存在悬空的情况。然后我们分析他和poster这一题非常相似,但是问题在于Poster可以覆盖,而其却不存在覆盖的情况。这样是不是就不能解决了呢?当然不是。我们可以把建筑物的高度从低到高排序,然后从低向高做,这样高的建筑物就相当于覆盖了较低的建筑物。

所以加一个离散化和sort就可以解决这个问题了。

不过这题在Poj上的时候,我弄了很多遍才过。不过数据是相当恶心,n<=7000000,而且这里读入的数据并不是<=10^9而是可能超过Int,只能用%lld 不能用%i64d,实在是太恶心了,而且这题如果换成Longlong还是专门卡Map的,想偷工减料用hash都不行,必须手工写二分哈希表。

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm> 
#include<map>
#define LL long long 
using namespace std;
const int MAX_N = 40001;
const int root = 1;
const int other = -1;
struct node
{
       LL s,e;
       LL high;
};
struct node p[MAX_N*10];
LL wide[MAX_N*10];
LL dote[MAX_N*10];
struct Treenode
{
       int L,R;
       int Lid,Rid;
       LL highest;
};
struct Treenode T[MAX_N*10];
int N;
int M;
int Q;
//map<LL,int> hash;
int times ;
struct Treenode Tn(int l,int r,int Lid,int Rid,LL highest)
{
 struct Treenode tmp;
 tmp.L=l;
 tmp.R=r;
 tmp.Lid=Lid;
 tmp.Rid=Rid;
 tmp.highest=highest;
 return tmp;
}
void Build(int l,int r)
{
     if (l>=r) {T[++times]=Tn(l,r,other,other,0);return;}
     int now = ++times;
     int mid = (l+r)/2;
     int lid= times+1;
     Build(l,mid);
     int rid= times+1;
     Build(mid+1,r);
     T[now]=Tn(l,r,lid,rid,0);
}
bool cmp(struct node a,struct node b)
{
     return a.high<=b.high;
}
void init()
{
     int i;
     int last;
     scanf("%d",&N);
     for (i=1;i<=N;i++)
     scanf("%lld %lld %lld",&p[i].s,&p[i].e,&p[i].high);
     for (i=1;i<=N;i++)
     wide[i]=p[i].s,wide[i+N]=p[i].e;
     sort(wide+1,wide+N*2+1);
     last=wide[1];
     M=2*N;
     for (i=2;i<=2*N;i++)
     {
         if (wide[i]-last>1)
         wide[++M]=last+1;
         last=wide[i];
     }
     sort(wide+1,wide+M+1);
     Q=0;
     last=-1;
     for (i=1;i<=M;i++)
     if (last!=wide[i])
     {
         last=wide[i];
         ++Q;
         //hash[last]=Q;
         dote[Q]=last;
     }
     ++Q;
     //hash[last+1]=Q;
     dote[Q]=last;
     Build(1,Q);
     sort(p+1,p+N+1,cmp);
}
void down_tag(int t)
{
     if (T[t].highest!=other)
     {
         int lid=T[t].Lid;
         int rid=T[t].Rid;
         T[lid].highest=T[t].highest;
         T[rid].highest=T[t].highest;
         T[t].highest = 0;
     }
}
void change(int t,int s,int e,LL color)
{
     int l=T[t].L;
     int r=T[t].R;
     int mid=(l+r)/2;
     int lid=T[t].Lid;
     int rid=T[t].Rid;
     if (s<=l&&e>=r) {T[t].highest=color;return ;}
     down_tag(t);
     T[t].highest=-1;
     if (s<=mid) change(lid,s,e,color);
     if (e>mid) change(rid,s,e,color);
}
int hash(LL v)
{
 int lb = 1;
 int rb = Q;
 while (lb<rb)
 {
  int mid=(lb+rb)/2;
  if (dote[mid]==v) return mid;
  if (dote[mid]>v) rb=mid-1;
  else lb=mid+1;
 } 
 return lb;
}
void work()
{
     int i;
     for (i=1;i<=N;i++)
     change(root,hash(p[i].s),hash(p[i].e)-1,p[i].high);
}
LL query(int t,int s,int e)
{
     int l=T[t].L;
     int r=T[t].R;
     int mid=(l+r)/2;
     int lid=T[t].Lid;
     int rid=T[t].Rid;
     if (T[t].highest!=-1) return T[t].highest*(dote[r+1]-dote[l]);
     down_tag(t);
     T[t].highest=-1;
     if (e<=mid||s>mid)
     return (s<=mid?query(lid,s,e):0)+(e>mid?query(rid,s,e):0);
     else
     return query(lid,s,mid)+query(rid,mid+1,e);
}
void put()
{
     printf("%lld\n",query(root,1,Q));
}
int main()
{
    freopen("horizon.in","r",stdin);
    freopen("horizon.out","w",stdout);
    init();
    work();
    put();
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值