版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leekerian/article/details/89341182
思路
将宽度从大到小排序,对于每一个宽度都有一个对应的高度,我们用线段的叶子节点表示为时间,并且维护这段时间的最大高度,每次我们遍历一个宽度,我们从线段树中查询从这个时间之后的这段时间里的最大高度,因为宽度是从大到小排序的,这个时候宽度是比前面的宽度小的我们找出这个时间之后的最大长度进行相减就可以了。
注意单点更新的时候是用else!!!!
复杂度nlogn
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define llson rt<<1
#define rrson rt<<1|1
#define ll long long
const int MAXN=50000+50;
struct node{
ll w,h;
int id;
}nd[MAXN];
ll stree[MAXN<<2];
void build(int l,int r,int rt)
{
stree[rt]=0;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
}
bool cmp1(node a,node b)
{
return a.w>b.w;
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return stree[rt];
}
int mid=(l+r)>>1;
ll ans=0;
if(L<=mid) ans=max(ans,query(L,R,lson));
if(R>mid) ans=max(ans,query(L,R,rson));
return ans;
}
void update(int L,int R,ll c,int l,int r,int rt)
{
if(l==r)
{
if(l==L)
{
stree[rt]=c;
return;
}
else
return;
}
int mid=(l+r)>>1;
if(L<=mid) update(L,R,c,lson);
else update(L,R,c,rson);
stree[rt]=max(stree[llson],stree[rrson]);
}
bool cmp2(node a,node b)
{
return a.h>b.h;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld%lld",&nd[i].w,&nd[i].h),nd[i].id=i+1;
build(1,n,1);
sort(nd,nd+n,cmp1);
ll ans=0;
for(int i=0;i<n;i++)
{
int k=query(nd[i].id,n,1,n,1);
if(nd[i].h>k)
ans+=nd[i].h-k;
update(nd[i].id,n,nd[i].h,1,n,1);
}
sort(nd,nd+n,cmp2);
build(1,n,1);
for(int i=0;i<n;i++)
{
int k=query(nd[i].id,n,1,n,1);
if(nd[i].w>k)
ans+=nd[i].w-k;
update(nd[i].id,n,nd[i].w,1,n,1);
}
printf("%lld\n",ans);
return 0;
}