传送门:洛谷P2061
题目描述
版本一:约翰带着奶牛去都市观光。在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线 上形成美丽的图案。以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有 重叠的部分。奶牛一共看到了 N 幢高楼,第 i 幢楼的高度是 Hi,两条边界轮廓在地平线上的坐标是 Ai 到 Bi。请帮助奶牛们计算一下,所有摩天高楼的轮廓覆盖的总面积是多少。
版本二:有一个数列,初始值均为0,他进行N次操作,每次将数列[ai,bi)这个区间中所有比Hi小的数改为Hi,他想知道N次操作后数列中所有元素的和。
分析
简易版本的面积并,一段固定,注意开long long
看到版本二的翻译,也不难想到另一种跟简单的思路,按照高度从小到大排序,直接区间覆盖,最后来一次统一的查询就行了
代码
指针版的线段树 (自从码过splay后,就喜欢用指针建树了)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define IL inline
#define ll long long
using namespace std;
IL int read()
{
char c = getchar();
int sum = 0 , k = 1;
for(; '0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(; '0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
return sum * k;
}
int n, m;
int num[40005];
struct Seg
{
int x, k;
ll y;
IL Seg(int x_ = 0, ll y_ = 0, int k_ = 0)
{
x = x_; y = y_; k = k_;
}
friend bool operator < (const Seg &a, const Seg &b)
{
return a.x < b.x;
}
}seg[80005];
struct node
{
node *lch, *rch;
ll len;
int cnt;
IL node()
{
lch = rch = 0; len = cnt = 0;
}
} *root;
IL void build(node *p, int l, int r)
{
if(l == r) return ;
int mid = (l + r) >> 1;
p->lch = new node; build(p->lch, l, mid);
p->rch = new node; build(p->rch, mid + 1, r);
}
IL void pushup(node *p, int l, int r)
{
if(p->cnt > 0)
p->len = num[r + 1] - num[l];
else
p->len = (l == r ? 0 : p->lch->len + p->rch->len);
}
IL void update(node *p, int l, int r, int x, int y, int k)
{
if(l == x && r == y)
{
p->cnt += k;
pushup(p, l, r);
return ;
}
int mid = (l + r) >> 1;
if(y <= mid) update(p->lch, l, mid, x, y, k); else
if(mid < x) update(p->rch, mid + 1, r, x, y, k); else
{
update(p->lch, l, mid, x, mid, k);
update(p->rch, mid + 1, r, mid + 1, y, k);
}
pushup(p, l, r);
}
int main()
{
m = n = read();
for(int i = 1, x, y, z, k = 0; i <= n; ++i)
{
x = read(); y = read(); z = read();
num[i] = z;
seg[++k] = Seg(x, z, 1); seg[++k] = Seg(y, z, -1);
}
n <<= 1;
num[++m] = 0;
sort(seg + 1, seg + n + 1);
sort(num + 1, num + m + 1);
m = unique(num + 1, num + m + 1) - (num + 1);
root = new node;
build(root, 1, m - 1);
ll ans = 0;
for(int i = 1; i <= n; ++i)
{
ans += (seg[i].x - seg[i - 1].x) * root->len;
seg[i].y = lower_bound(num + 1, num + m + 1, seg[i].y) - num - 1;
update(root, 1, m - 1, 1, seg[i].y, seg[i].k);
}
printf("%lld", ans);
return 0;
}