HDOJ 1828 线段树 矩形周长并

链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1828

代码:

 1 #include <map>
 2 #include <set>
 3 #include <cmath>
 4 #include <queue>
 5 #include <stack>
 6 #include <cstdio>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdlib>
10 #include <cstring>
11 #include <sstream>
12 #include <iostream>
13 #include <algorithm>
14 #include <functional>
15 using namespace std;
16 #define rep(i,a,n) for (int i=a;i<n;i++)
17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
18 #define all(x) (x).begin(),(x).end()
19 #define pb push_back
20 #define mp make_pair
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1
23 typedef long long ll;
24 typedef vector<int> VI;
25 typedef pair<int, int> PII;
26 const ll MOD = 1e9 + 7;
27 const int INF = 0x3f3f3f3f;
28 const int MAXN = 2e4 + 7;
29 // head
30
31 int cnt[MAXN << 2];
32 int sum[MAXN << 2], num[MAXN << 2];
33 int lbd[MAXN << 2], rbd[MAXN << 2];
34
35 struct seg {
36     int l, r, h, d;
37     const bool operator<(const seg &t) const {
38         return h < t.h;
39     }
40 }s[MAXN << 1];
41
42 void pushup(int l, int r, int rt) {
43     if (cnt[rt]) {
44         lbd[rt] = rbd[rt] = 1;
45         sum[rt] = r - l + 1;
46         num[rt] = 2;
47     }
48     else if (l == r) lbd[rt] = rbd[rt] = sum[rt] = num[rt] = 0;
49     else {
50         lbd[rt] = lbd[rt << 1], rbd[rt] = rbd[(rt << 1) | 1];
51         sum[rt] = sum[rt << 1] + sum[(rt << 1) | 1];
52         num[rt] = num[rt << 1] + num[(rt << 1) | 1];
53         if (rbd[rt << 1] && lbd[(rt << 1) | 1]) num[rt] -= 2;
54     }
55 }
56
57 void update(int L, int R, int d, int l, int r, int rt) {
58     if (L <= l && r <= R) {
59         cnt[rt] += d;
60         pushup(l, r, rt);
61         return;
62     }
63     int m = (l + r) >> 1;
64     if (L <= m) update(L, R, d, lson);
65     if (R > m) update(L, R, d, rson);
66     pushup(l, r, rt);
67 }
68
69 int main() {
70     int n;
71     while (cin >> n) {
72         int m = 0;
73         rep(i, 0, n) {
74             int x1, x2, y1, y2;
75             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
76             s[m++] = seg{ x1,x2,y1,1 };
77             s[m++] = seg{ x1,x2,y2,-1 };
78         }
79         sort(s, s + m);
80         int ans = 0, last = 0;
81         rep(i, 0, m) {
82             if (s[i].l < s[i].r) update(s[i].l, s[i].r - 1, s[i].d, -1e4, 1e4, 1);
83             ans += num[1] * (s[i + 1].h - s[i].h);
84             ans += abs(sum[1] - last);
85             last = sum[1];
86         }
87         cout << ans << endl;
88     }
89     return 0;
90 }
时间: 2024-12-11 16:06:26

HDOJ 1828 线段树 矩形周长并的相关文章

hdu1828(线段树——矩形周长并)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 分析:与面积不同的地方是还要记录竖的边有几个(num记录),并且当边界重合的时候需要合并(用lbd和rbd表示边界来辅助) 线段树操作:update:区间增减 query:直接取根节点的值 #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

HDU 1828 Picture(矩形周长并)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

HDU 1828 扫描线(矩形周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3310    Accepted Submission(s): 1723 Problem Description A number of rectangular posters, photographs and other pictures of the same shape

hdu1542(线段树——矩形面积并)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 分析:离散化+扫描线+线段树 #pragma comment(linker,"/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #in

51nod 1206 &amp;&amp; hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴和Y轴),求这些矩形组成的所有多边形的周长之和. 例如:N = 7.(矩形会有重叠的地方). 合并后的多边形: 多边形的周长包括里面未覆盖部分方块的周长. Input 第1行:1个数N.(2 <= N <= 50000) 第2 - N + 1行,每行4个数,中间用空格分隔,分别表示矩形左下和右上端

hdu1255(线段树——矩形面积交)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意:求N个矩形中,求被覆盖至少俩次的面积和 分析:覆盖两次即col[rt]>=2就好.一开始将线段pushdown到叶子节点,根据col[rt]>=2才pushup上来,差点超时了,其实可以lazy标志,整段更新的,只是没想到而已. 用sum[rt][0]表示该节点rt代表的线段被覆盖一次的长度之和,则 if(col[rt])sum[rt][0]=pos[r+1]-pos[l];//整段被

hdu1828 Picture (线段树:扫描线周长)

依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖着都做一遍就行了 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 10010 5 #define ll long long 6 using namespace std;

HDOJ 3911 线段树

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给出01串 1代表黑色 0代表白色 0 a b:询问[a,b]中1的连续最大长度 1 a,b:把[a,b]区间的0->1 1->0 题解: lsum1[],rsum1[],msum1[]分别表示区间左起连续1的最大长度,右起连续1的最大长度,区间1的最大连续长度 lsum0[],rsum0[],msum0[]分别表示区间左起连续0的最大长度,右起连续0的最大长度,区间连续0的最大连续长