pku3277 horizon
阿新 • • 發佈:2019-02-07
首先,看到這題就感覺亮瞎,好像沒有任何突破口,因為以前做過一個矩陣求並的問題,那個題目還是比較難的,但是這道題目和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; }