1. 程式人生 > >pku3277 horizon

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;
}