题意:就是有一些矩形,然后让你输出一些点,这些点连成的线是这些矩形的外围。叫做城市天际线。具体的看题目就好了。
题解:首先,设立一个区间,用数组表示。每遇到一个矩形,我们就把这个矩形的底部的宽所占的区间的值全部都设成这个矩形的高。在覆盖区间的时候,如果发现这个区间已经被覆盖过,如果当前值比原有值低,就不覆盖了,比原有值高采取覆盖。一开始的区间的长度当然是0,相当于这个城市都是平地。当我们把所有矩形都覆盖之后,把区间的长度当做宽,当做高,就是上面图片中的第二张。然后那些点,怎么确定呢?其实就是从区间的最左边开始,遇到第一个值发生变化的那个点,是我们需要的,然后从这个点再向右找,找到区间值又发生变化的下一个点。以此循环,直到发现某个点向右的值都没有变化了,就停止了。
那上面一系列操作,最合适的数据结构就是线段树了,可以满足的我们的需求。覆盖点,以及找到某个点开始,第一个值发生变化的点。
但是题目的数据范围是0-INTMAX,直接建立线段树会炸的,所以我们必须要离散化!
typedef long long int _int;
class Solution {
public:
int num[500005];
int height;
map<_int,int> m;
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<vector<int>> ans;
if(buildings.size()==0)
return ans;
memset(num,0,sizeof(num));
vector<_int> a;
for(int i=0;i<buildings.size();i++)
{
a.push_back(buildings[i][0]);
a.push_back(buildings[i][1]);
a.push_back((_int)buildings[i][1]+1);
}
sort(a.begin(),a.end());
int pos=0;
vector<_int> b;
for(int i=0;i<a.size();i++)
{
if(m[a[i]]==0)
{
m[a[i]] = ++pos;
b.push_back(a[i]);
}
}
int last;
for(int i=0;i<buildings.size();i++)
{
update(1,1,pos+2,m[buildings[i][0]],m[buildings[i][1]],buildings[i][2]);
}
_int start=1;
height = 0;
int pre = height;
while(1)
{
pre = height;
start = query(1,1,pos+2,start,height);
if(start==-1)
{
break;
}
vector<int> res;
if(height < pre)
res.push_back(b[start-1]-1);
else
res.push_back(b[start-1]);
res.push_back(height);
ans.push_back(res);
}
return ans;
}
void pushup(int node)
{
if(num[node<<1]==num[node<<1|1])
num[node]=num[node<<1];
else
num[node]=-1;
}
void pushdown(int node)
{
if(num[node]!=-1)
{
num[node<<1]=num[node];
num[node<<1|1]=num[node];
}
}
void update(int node,_int l,_int r,_int start,_int end,int val)
{
if(start<=l&&r<=end)
{
if(num[node]!=-1)
{
if(num[node]<val)
num[node]=val;
return;
}
}
pushdown(node);
_int mid = (l+r)>>1;
if(start<=mid)
update(node<<1,l,mid,start,end,val);
if(end >mid)
update(node<<1|1,mid+1,r,start,end,val);
pushup(node);
}
int query(int node,_int l,_int r,_int start,_int val)
{
if(num[node]!=-1)
{
if(num[node]==val)
return -1;
else
{
height = num[node];
return l;
}
}
pushdown(node);
_int mid = (l+r)>>1;
int res;
if(start<=mid)
{
res = query(node<<1,l,mid,start,val);
if(res!=-1)
return res;
}
res = query(node<<1|1,mid+1,r,start,val);
pushup(node);
return res;
}
};