Question link: http://poj.org/problem? Id = 3277
This is my first question of discretization and the combination of line tree in the real sense. After a long time, I continuously patch and finally AC. I have learned a lot from this question.
1. The idea of discretization
2. the array subscript build method of the Line Segment tree (all previous methods used to create a tree with pointers on the array)
3. L> 1 + 1 is to do 1 + 1 first, that is, L> 1 + 1 <=> L> 2. It has been pitted for a long time, so do not take operators that are not very familiar with them for granted.
4. It is easier to create a line segment tree by array subscript and the method of creating a tree by array subscript under the corresponding operation conditions to run the program faster (not the array subscript is faster, but the operation is simpler)
I started to look at this question and never understood how discretization was going. But now I understand that there are so many Integer Points in a straight line. If we want to build a line segment tree in one unit
If the time-out period is not mentioned, you cannot open the memory. Considering that the number of given rectangles is limited, discretization means that you don't understand discretization at first, but you don't understand why it works. Now you understand it.
First, sort all online vertices, and then create a range based on these vertices. Think about the following of all the rectangles only between these vertices, that is, I just need to edit these points from left to right.
And then create a line segment tree. Then, you can use binary search to find the numbers corresponding to the left and right subscripts of the rectangle and then update the range.
It should be well understood.
In the following program, I think this code still needs to be explained:
If (re_root [root]. L + 1! = Re_root [root]. R & re_root [root]. H! =-1)
Re_root [root <1]. H = re_root [(root <1) + 1]. H = re_root [root]. h, re_root [root]. H =-1;
The above code is a piece of code pulled down during the insertion process. When the entire large range is root, if the next update involves this range, it is not the whole range.
Then, the unupdated H will be pulled down, because a section of the current range is not h, so we need to pull down and change the H of this range to-1,
In fact, "-1" means to tell you to query down when querying. Either there is no rectangle in this interval, or there is a rectangle with different heights (the height is 0 and the height is not
A rectangle with a height of 0 is also regarded as a rectangle of different heights)
During insertion, the height is sorted from small to large, which saves time during insertion. In fact, it is no big deal to sort without sorting!
The AC code for creating the line tree by array subscript (modified by pointer version ):
# Include <iostream> # include <string. h> # include <algorithm> # include <stdio. h> using namespace STD; # define maxn 440004 struct point {long l, R, H;} org [maxn]; struct node {long l, R; long long h;} re_root [maxn]; long n; long cut [maxn * 3]; bool CMP1 (const point & A, const point & B) {return. h <B. h;} long Pos; int build_tree (long root, long l, long R) {re_root [root]. L = L, re_root [Root]. R = r; re_root [root]. H =-1; if (L + 1 = r) return 0; long mid = (L + r)> 1; build_tree (root <1, l, mid); build_tree (root <1) + 1, mid, R); // return 0;} int find_num (long l, long R, long long num) {long mid; while (L <= r) {mid = (L + r)> 1; if (cut [Mid] = num) return mid; If (cut [Mid]> num) r = mid-1; else l = Mid + 1;} return 0;} int insert (long root, long long l, long R, long num) {If (Num <= Re_root [root]. h) Return 0; If (re_root [root]. L = L & re_root [root]. R = r) {re_root [root]. H = num; return 0;} If (re_root [root]. L + 1! = Re_root [root]. R & re_root [root]. H! =-1) re_root [root <1]. H = re_root [(root <1) + 1]. H = re_root [root]. h, re_root [root]. H =-1; if (re_root [root]. L + 1 = re_root [root]. r) return 0; long mid = (re_root [root]. L + re_root [root]. r)> 1; if (r <= mid) insert (root <1, L, R, num); else if (L> = mid) insert (root <1) + 1, L, R, num); else insert (root <1, L, mid, num ), insert (root <1) + 1, mid, R, num); Return 0;} long find_ans (long root) {If (re_root [root]. h! =-1) {// printf ("% LLD \ n", cut [re_root [root]. r], cut [re_root [root]. l], re_root [root]. h); Return (long) (cut [re_root [root]. r]-cut [re_root [root]. l]) * re_root [root]. h);} If (re_root [root]. L + 1 = re_root [root]. r) return 0; long mid = (re_root [root]. L + re_root [root]. r)> 1; return find_ans (root <1) + find_ans (root <1) + 1);} int main () {long I, j, k, R, L; while (scanf ("% LLD", & N )! = EOF) {k = 0; Pos = 1; for (I = 0; I <n; I ++) {scanf ("% LLD ", & ORG [I]. l, & ORG [I]. r, & ORG [I]. h); cut [k ++] = org [I]. l, cut [k ++] = org [I]. r;} Sort (cut, cut + k); sort (ORG, org + N, CMP1); r = 1; for (I = 1; I <K; I ++) if (cut [I]! = Cut [I-1]) Cut [R ++] = cut [I]; k = r; build_tree (, k-1); for (I = 0; I <N; I ++) {L = find_num (0, K-1, org [I]. l); r = find_num (0, K-1, org [I]. r); insert (1, L, R, org [I]. h);} printf ("% LLD \ n", find_ans (1);} return 0 ;}
The TLE code of the pointer:
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>using namespace std;#define maxn 440004struct point{ long long l,r,h;}org[maxn];struct node{ long long L,R; long long h; node *left,*right;}re_root[maxn];long long n;long long cut[maxn*3];bool cmp1(const point &a,const point &b){ return a.h < b.h;}long long pos;int build_tree(node *root){ if(root->L+1 == root->R) return 0; long long mid=(root->L+root->R)>>1; root->left=&re_root[pos]; re_root[pos].h=-1,re_root[pos].L=root->L,re_root[pos++].R=mid; build_tree(root->left); root->right=&re_root[pos]; re_root[pos].L=mid,re_root[pos].R=root->R,re_root[pos++].h=-1; build_tree(root->right); return 0;}int find_num(long long l,long long r,long long num){ long long mid; while(l<=r) { mid=(l+r)>>1; if(cut[mid]==num) return mid; if(cut[mid]>num) r=mid-1; else l=mid+1; } return 0;}int insert(node *root,long long l,long long r,long long num){ if(root->h >= num) return 0; if(root->L+1 == root->R) { root->h=num; return 0; }if(root->L+1!=root->R && root->h !=-1)root->left->h=root->right->h=root->h,root->h=-1; long long mid=(root->L + root->R)>>1; if(r <= mid) insert(root->left,l,r,num); else if(l>=mid) insert(root->right,l,r,num); else insert(root->left,l,mid,num),insert(root->right,mid,r,num); return 0;}long long find_ans(node *root){ if(root->h!=-1) { return ((long long)(cut[root->R]-cut[root->L])*root->h); } if(root->L+1 == root->R) return 0; long long mid=(root->L+root->R)>>1; return find_ans(root->left)+find_ans(root->right);}int main(){ long long i,j,k,r,l; while(scanf("%lld",&n)!=EOF) { k=0; pos=1; for(i=0;i<n;i++) { scanf("%lld%lld%lld",&org[i].l,&org[i].r,&org[i].h); cut[k++]=org[i].l,cut[k++]=org[i].r; } sort(cut,cut+k); // sort(org,org+n,cmp1); r=1; for(i=1;i<k;i++) if(cut[i]!=cut[i-1]) cut[r++]=cut[i]; k=r; re_root[0].L=0,re_root[0].R=k-1,re_root[0].h=-1; build_tree(&re_root[0]); for(i=0;i<n;i++) { l=find_num(0,k-1,org[i].l); r=find_num(0,k-1,org[i].r); insert(&re_root[0],l,r,org[i].h); } printf("%lld\n",find_ans(&re_root[0]));//<<endl; } return 0;}