题意:给定每个矩形的高度以及底边在数轴上的起点和终点。各矩形间可能有重叠。问它们覆盖的总面积是多少。
离散化后线段树,数组下标排序,unique去重,lower_bound二分查找数组下标
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<utility>
using namespace std;
typedef long long ll;
struct aa
{
int l,r,h;
}a[4*100000+9];
int n,nn;
int x[100009],y[100009],h[100009];
int q[100009];
void build(int i,int l,int r)
{
a[i].l=l;a[i].r=r;
a[i].h=0;
if (l+1==r) return;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid,r);
}
void updata(int i,int l,int r,int k)
{
if (a[i].l==l&&a[i].r==r)
{
a[i].h=max(a[i].h,k);
return ;
}
if (a[i].l+1==a[i].r) return ;
int mid=(a[i].l+a[i].r)>>1;
if (a[i].h>0)
{
a[i<<1].h=max(a[i<<1].h,a[i].h);
a[i<<1|1].h=max(a[i<<1|1].h,a[i].h);
a[i].h=0;
}//lazy思想
if (mid>=r) updata(i<<1,l,r,k);
else if (mid<=l) updata(i<<1|1,l,r,k);
else updata(i<<1,l,mid,k),updata(i<<1|1,mid,r,k);
}
ll find(int i)
{
if (a[i].l+1==a[i].r)
{
return (ll)(q[a[i].r]-q[a[i].l])*(a[i].h);
}
if (a[i].h>0)
{
a[i<<1].h=max(a[i<<1].h,a[i].h);
a[i<<1|1].h=max(a[i<<1|1].h,a[i].h);
a[i].h=0;
}
return find(i<<1)+find(i<<1|1);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&h[i]);
q[i*2]=x[i];
q[i*2-1]=y[i];
}
sort(q+1,q+2*n+1);
nn=unique(q+1,q+2*n+1)-(q+1);
build(1,1,nn);
int l,r;
for (int i=1;i<=n;i++)
{
l=lower_bound(q+1,q+nn+1,x[i])-q;
r=lower_bound(q+1,q+nn+1,y[i])-q;
updata(1,l,r,h[i]);
}
ll ans=find(1);
printf("%lld",ans);
return 0;
}
set就可以完成这件事
将2*n个点进行排序 记录好是左端点还是右端点
关键是维护当前的高度是多少
set支持插入 删除 还有查询最大值 非常好
然后依次扫描 如果是左端点 就插入高度
反之删除高度
同时代码中运用各种以stl为基础的技巧
#define debug(x) cout<<#x<<"="<<x<<endl
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<utility>
#include<set>
#define MK(x,y) make_pair(x,y)//make_pair
#define fi first//第一关键字
#define debug(x) cout<<#x<<"="<<x<<endl//黑科技debug
<pre name="code" class="cpp">#define se second//第二关键字
#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int> pii;//简化typedef long long ll;int n; pair<pii,bool> a[500009];int main(){scanf("%d",&n);int x,y,z;for (int i=1;i<=n;i++){scanf("%d%d%d",&x,&y,&z);a[i].fi.fi=x;a[i+n].fi.fi=y;a[i].fi.se=a[i+n].fi.se=z;a[i].se=true;a[i+n].se=false;}sort(a+1,a+n*2+1);multiset<int> s;multiset<int>::iterator it; s.insert(0);ll ans=0;for (int i=1;i<=2*n;i++){ans+=(ll)(a[i].fi.fi-a[i-1].fi.fi)*(*s.rbegin());//最大的数,*s.rbegin代表最后一个数字,也就是最大一个if (a[i].se) s.insert(a[i].fi.se);else it=s.find(a[i].fi.se),s.erase(it);}printf("%lld",ans);return 0;}