[USACO07OPEN] City Horizon

题目描述

Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.

The entire horizon is represented by a number line with N (1 ≤ N ≤ 40,000) buildings. Building i’s silhouette has a base that spans locations Ai through Bi along the horizon (1 ≤ Ai < Bi ≤ 1,000,000,000) and has height Hi (1 ≤ Hi ≤ 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.

有一个数列,初始值均为0,他进行N次操作,每次将数列[ai,bi)这个区间中所有比Hi小的数改为Hi,他想知道N次操作后数列中所有元素的和。

输入格式

第一行一个整数N,然后有N行,每行三个正整数ai、bi、Hi。

输出格式

一个数,数列中所有元素的和。

题意翻译

约翰带着奶牛去都市观光。在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线 上形成美丽的图案。以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有 重叠的部分。奶牛一共看到了 N 幢高楼,第 i 幢楼的高度是 Hi,两条边界轮廓在地平线上的坐标是 Ai 到 Bi。请帮助奶牛们计算一下,所有摩天高楼的轮廓覆盖的总面积是多少。

一句话解释题意,维护区间 m a x max

我们想到线段树,懒标记也挺好打的,离散化一下就好了,代码难度也不是很高

但是

我们想再把代码难度降低一点——这种 N 40000 N\leq 40000 的题, n l o g n nlogn 绰绰有余,还不如写个 n n n\sqrt n 的分块呢?

首先先离散化一下,设离散化完了的数组大小是 s z sz 那么我们构建 s z 1 \sqrt {sz-1} 个块,因为只有这么多区间

i i 个块表示的是区间 [ b [ i ] , b [ i + 1 ] ) [b[i],b[i+1]) 的高度(设 b b 是离散化数组)

那么就很好写了

# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;

# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)

typedef long long ll;
const int N=1e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
	x=0;int f=1;
	char c=getchar();
	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
	x*=f;
}

# define int long long

int n,sz,sq,ans;
int b[N];

struct node{
	int l,r,h;	
}q[N];

int pos[N],l[N],r[N],a[N],tag[N];

void update(int l,int r,int k){
	for(int i=l;i<=min(r,pos[l]*sq);i++)
		a[i]=max(max(a[i],tag[pos[l]]),k);
	if(pos[l]!=pos[r])
		for(int i=(pos[r]-1)*sq+1;i<=r;i++)
			a[i]=max(max(a[i],tag[pos[r]]),k);
	Rep(i,pos[l]+1,pos[r]-1)tag[i]=max(tag[i],k);
}

signed main()
{
	read(n);
	Rep(i,1,n)read(q[i].l),read(q[i].r),read(q[i].h);
	Rep(i,1,n)b[i]=q[i].l,b[i+n]=q[i].r;
	sort(b+1,b+2*n+1);
	sz=unique(b+1,b+2*n+1)-b-1;
	sq=sqrt(sz-1);
	Rep(i,1,sz-1)pos[i]=(i-1)/sq+1;
	Rep(i,1,n)q[i].l=lower_bound(b+1,b+sz+1,q[i].l)-b;
	Rep(i,1,n)q[i].r=lower_bound(b+1,b+sz+1,q[i].r)-b;
	Rep(i,1,n)update(q[i].l,q[i].r-1,q[i].h);	
	Rep(i,1,sz-1)ans+=(b[i+1]-b[i])*max(a[i],tag[pos[i]]);
	printf("%lld\n",ans);
	return 0;
}
发布了45 篇原创文章 · 获赞 52 · 访问量 9653

猜你喜欢

转载自blog.csdn.net/devout_/article/details/104122442
今日推荐