BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线

Description

N个矩形块,交求面积并.

Input

* Line 1: A single integer: N

* Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: A_i, B_i, and H_i

Output

* Line 1: The total area, in square units, of the silhouettes formed by all N buildings

Sample Input

4
2 5 1
9 10 4
6 8 2
4 6 3

Sample Output

16



裸的扫描线,这里从左往右扫。

先将x轴向上平移一个单位,避免处理麻烦的区间长度问题。

然后每个矩形拆成两条竖线,从左往右扫。

需要在线段树上维护一些点是否存在。

每个节点记录sum和raw,当sum>0时raw=r-l+1,否则等于两个儿子的raw之和,每次修改都要pushup一下。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 80050
#define maxn 1000000000
struct Line {
    int y_1,y_2,x,flg;
    Line() {}
    Line(int y__1,int y__2,int x_,int flg_) :
        y_1(y__1),y_2(y__2),x(x_),flg(flg_) {}
    bool operator < (const Line &u) const {
        return x<u.x;
    }
}a[N];
int t[N*40],ls[N*40],rs[N*40],cnt,n,raw[N*40],add[N*40];
void pushdown(int l,int r,int &p,int v) {
    if(!p) p=++cnt;
    t[p]+=(r-l+1)*v; add[p]+=v;
}
void pushup(int l,int r,int p) {
    if(t[p]>0) raw[p]=r-l+1;
    else if(l==r) raw[p]=0;
    else raw[p]=raw[ls[p]]+raw[rs[p]];
}
void update(int l,int r,int x,int y,int v,int &p) {
    if(!p) p=++cnt;
    if(x<=l&&y>=r) {
        t[p]+=v; pushup(l,r,p);
        return ;
    }
    int mid=(l+r)>>1;
    if(add[p]) {
        pushdown(l,mid,ls[p],add[p]); pushdown(mid+1,r,rs[p],add[p]); add[p]=0;
    }
    if(x<=mid) update(l,mid,x,y,v,ls[p]);
    if(y>mid) update(mid+1,r,x,y,v,rs[p]);
    pushup(l,r,p);
}
int main() {
    scanf("%d",&n);
    int i,x_1,x_2,h,tot=0;
    for(i=1;i<=n;i++) {
        scanf("%d%d%d",&x_1,&x_2,&h);
        a[++tot]=Line(1,h,x_1,1);
        a[++tot]=Line(1,h,x_2,-1);
    }
    sort(a+1,a+tot+1);
    int root=0;
    update(1,maxn,a[1].y_1,a[1].y_2,a[1].flg,root);
    long long ans=0;
    for(i=2;i<=tot;i++) {
        ans+=1ll*(a[i].x-a[i-1].x)*raw[1];
        update(1,maxn,a[i].y_1,a[i].y_2,a[i].flg,root);
    }
    printf("%lld\n",ans);
}

原文地址:https://www.cnblogs.com/suika/p/9063254.html

时间: 2024-08-29 13:09:09

BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线的相关文章

1645: [Usaco2007 Open]City Horizon 城市地平线

1645: [Usaco2007 Open]City Horizon 城市地平线 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 315  Solved: 157[Submit][Status] Description 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 t

BZOJ1645 [Usaco2007 Open]City Horizon 城市地平线

本来想打线段树的说... 就是把坐标离散化了,然后区间最大求和即可... 后来觉得有点烦的说(silver题就要线段树...),于是看了下usaco的题解,发现了个高端的东西:善用STL里的容器和迭代器就可以了. 以下就是高端程序: 1 /************************************************************** 2 Problem: 1645 3 User: rausen 4 Language: C++ 5 Result: Accepted 6

bzoj1683[Usaco2005 Nov]City skyline 城市地平线

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1683 Input 第1行:2个用空格隔开的整数N和W. 第2到N+1行:每行包括2个用空格隔开的整数x,y,其意义如题中所述.输入中的x严格递增,并且第一个z总是x. Output 输出一个整数,表示城市中最少包含的建筑物数量. Sample Input 10 26 1 1 2 2 5 1 6 3 8 1 11 0 15 2 17 3 20 2 22 1 INPUT DETAILS: T

bzoj1645 / P2061 [USACO07OPEN]城市的地平线City Horizon(扫描线)

P2061 [USACO07OPEN]城市的地平线City Horizon 扫描线 扫描线简化版 流程(本题为例): 把一个矩形用两条线段(底端点的坐标,向上长度,添加$or$删除)表示,按横坐标排序 $upd:$本题的底端点坐标简化为$(x,0)$ 蓝后对纵坐标建一棵线段树(本题需要对高度进行离散化). 每次对线段树进行覆盖$or$删除区间操作,顺便统计一下$k=$有多少点被覆盖到 而两次(线段)操作之间的长度为$r=x_{i}-x_{i-1}$ 于是两条线段之间被覆盖的面积即为$k*r$ (

BZOJ1628: [Usaco2007 Demo]City skyline

1628: [Usaco2007 Demo]City skyline Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 256  Solved: 210[Submit][Status] Description The best part of the day for Farmer John's cows is when the sun sets. They can see the skyline of the distant city. Bessie w

POJ 3277 City Horizon

City Horizon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18555   Accepted: 5114 Description 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 silhouette

xtu数据结构 H. City Horizon

H. City Horizon Time Limit: 2000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main 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 silh

ACM基础训练题解4301 城市地平线

遍历线段树   线段树的插入和查询 1 //城市地平线(线段树) 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cstdio> 7 using namespace std; 8 typedef __int64 LL; 9 struct building{ 10 LL x1; 11 LL x2; 12 LL

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <