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

我的做法是把x轴的表示为线段,然后更新y

不考虑什么优化的话,开始的时候,把他们表达成线段,并按y排序,然后第一次加入线段树的应该就是最底下那条,然后第二条的时候,我们可以询问第二条那段区间,有多少是已经被覆盖的,然后把面积算上就可以。

所以如果区间都是整数,而且数值很少,那么就是线段树成段覆盖的问题了。但是这里是浮点数而且很大。

所以只能把它离散化。

这个时候线段树就不是连续的了,这里就有bug,问题就变成了怎么表达这颗线段树了。

思路是把它弄成L + 1 == R就是叶子节点,这样的话,每个节点都保存了一个区间了,

例如

要保存5、10、15、30

一般的线段树

      5、30

   5、10   15、30

  5    10    15         30

但是这样怎么表示[10, 15]这段区间呢?

所以把线段树变成

      5、30

    5、10   10、 30

        10、15  15、30

就行了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string> int n;
const int maxn = 2e2 + ;
struct node {
int L, R;
double x1, x2, y;
int cover;
} seg[maxn << ];
struct info {
double x1, x2, y;
int flag;
bool operator < (const struct info & rhs) const {
return y < rhs.y;
}
} in[maxn];
double xx[maxn];
void build(int L, int R, int cur) {
seg[cur].cover = ;
seg[cur].x1 = xx[L];
seg[cur].x2 = xx[R];
seg[cur].y = -;
seg[cur].L = L;
seg[cur].R = R;
if (L + == R) { //两个节点作为一个叶子
return;
}
int mid = (L + R) >> ;
build(L, mid, cur << );
build(mid, R, cur << | );
}
double upDate(int begin, int end, double y, int flag, int cur) {
if (end <= seg[cur].L || begin >= seg[cur].R) return ;
if (seg[cur].L + == seg[cur].R) {
if (seg[cur].cover) {
double ans = (seg[cur].x2 - seg[cur].x1) * (y - seg[cur].y);
seg[cur].cover += flag;
seg[cur].y = y;
return ans;
} else {
seg[cur].cover += flag;
seg[cur].y = y;
return ;
}
}
double ans = upDate(begin, end, y, flag, cur << ) + upDate(begin, end, y, flag, cur << | );
return ans;
}
void work() {
int lenin = ;
int lenxx = ;
for (int i = ; i <= n; ++i) {
double xx1, xx2, yy1, yy2;
scanf("%lf%lf%lf%lf", &xx1, &yy1, &xx2, &yy2);
lenin++;
in[lenin].x1 = xx1;
in[lenin].x2 = xx2;
in[lenin].y = yy1;
in[lenin].flag = ;
lenxx++;
xx[lenxx] = xx1; lenin++;
in[lenin].x1 = xx1;
in[lenin].x2 = xx2;
in[lenin].y = yy2;
in[lenin].flag = -;
lenxx++;
xx[lenxx] = xx2;
}
sort(in + , in + + lenin);
sort(xx + , xx + + lenxx);
lenxx = unique(xx + , xx + + lenxx) - (xx + );
build(, lenxx, );
double ans = ;
const int root = ;
for (int i = ; i <= lenxx; ++i) {
printf("%f**\n", xx[i]);
}
for (int i = ; i <= lenin; ++i) {
int L = lower_bound(xx + , xx + + lenxx, in[i].x1) - xx;
int R = lower_bound(xx + , xx + + lenxx, in[i].x2) - xx;
// cout << L << " " << R << endl;
ans += upDate(L, R, in[i].y, in[i].flag, root);
}
static int f = ;
printf("Test case #%d\n", ++f);
printf("Total explored area: %0.2f\n", ans);
// printf("%0.2f\n", ans);
}
int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
while (scanf("%d", &n) != EOF && n) {
work();
printf("\n");
}
return ;
}
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 1e3 + ;
struct Node {
double x1, x2, y;
int L, R;
int cover;
}seg[maxn << ];
vector<double> vc;
int n;
struct Info {
double x1, x2, y;
int cover;
bool operator < (const struct Info & rhs) const {
return y < rhs.y;
}
}fuck[maxn * ];
void build(int L, int R, int cur) {
seg[cur].L = L, seg[cur].R = R;
seg[cur].x1 = vc[L], seg[cur].x2 = vc[R];
seg[cur].y = -inf;
seg[cur].cover = ;
if (L + == R) return;
int mid = (L + R) >> ;
build(L, mid, cur << );
build(mid, R, cur << | );
}
double add(int x1, int x2, double y, int cover, int cur) {
if (x2 <= seg[cur].L || x1 >= seg[cur].R) return ;
if (seg[cur].L + == seg[cur].R) {
if (seg[cur].cover) {
double res = (y - seg[cur].y) * (seg[cur].x2 - seg[cur].x1);
seg[cur].cover += cover;
seg[cur].y = y; // 更新最大值y
return res;
} else {
seg[cur].cover += cover;
seg[cur].y = y;
return ;
}
}
return add(x1, x2, y, cover, cur << ) + add(x1, x2, y, cover, cur << | );
}
void work() {
vc.clear();
vc.push_back(-1.0);
int len = ;
for (int i = ; i <= n; ++i) {
double x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
++len;
fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y1, fuck[len].cover = ;
++len;
fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y2, fuck[len].cover = -;
vc.push_back(x1);
vc.push_back(x2);
}
sort(vc.begin(), vc.end());
sort(fuck + , fuck + + len);
build(, vc.size(), );
double ans = ;
for (int i = ; i <= len; ++i) {
int x1 = lower_bound(vc.begin(), vc.end(), fuck[i].x1) - vc.begin();
int x2 = lower_bound(vc.begin(), vc.end(), fuck[i].x2) - vc.begin();
ans += add(x1, x2, fuck[i].y, fuck[i].cover, );
}
static int f = ;
printf("Test case #%d\n", ++f);
printf("Total explored area: %.2f\n\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
while (cin >> n && n) work();
return ;
}

跪着看这篇blog想的

http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html

2017年8月15日 13:35:12

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

只需要cover >= 2才计算

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 1e3 + ;
struct Node {
double x1, x2, y;
int L, R;
int cover;
}seg[maxn << ];
vector<double> vc;
int n;
struct Info {
double x1, x2, y;
int cover;
bool operator < (const struct Info & rhs) const {
return y < rhs.y;
}
}fuck[maxn * ];
void build(int L, int R, int cur) {
seg[cur].L = L, seg[cur].R = R;
seg[cur].x1 = vc[L], seg[cur].x2 = vc[R];
seg[cur].y = -inf;
seg[cur].cover = ;
if (L + == R) return;
int mid = (L + R) >> ;
build(L, mid, cur << );
build(mid, R, cur << | );
}
double add(int x1, int x2, double y, int cover, int cur) {
if (x2 <= seg[cur].L || x1 >= seg[cur].R) return ;
if (seg[cur].L + == seg[cur].R) {
if (seg[cur].cover >= ) {
double res = (y - seg[cur].y) * (seg[cur].x2 - seg[cur].x1);
seg[cur].cover += cover;
seg[cur].y = y; // 更新最大值y
return res;
} else {
seg[cur].cover += cover;
seg[cur].y = y;
return ;
}
}
return add(x1, x2, y, cover, cur << ) + add(x1, x2, y, cover, cur << | );
}
void work() {
vc.clear();
vc.push_back(-1.0);
int len = ;
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
double x1, y1, x2, y2;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
++len;
fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y1, fuck[len].cover = ;
++len;
fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y2, fuck[len].cover = -;
vc.push_back(x1);
vc.push_back(x2);
}
sort(vc.begin(), vc.end());
sort(fuck + , fuck + + len);
build(, vc.size(), );
double ans = ;
for (int i = ; i <= len; ++i) {
int x1 = lower_bound(vc.begin(), vc.end(), fuck[i].x1) - vc.begin();
int x2 = lower_bound(vc.begin(), vc.end(), fuck[i].x2) - vc.begin();
ans += add(x1, x2, fuck[i].y, fuck[i].cover, );
}
printf("%.2f\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}

http://codeforces.com/contest/610/problem/D

这题要用到另一种方法

不然TLE

这题是把线条表达成一个长度大小是1的矩形

如果矩形表达成[x1, x2],那么边长应该是x2 - x1 + 1(因为在直线的意义下所有点都覆盖了)

所以要把矩形表达成[x1 - 1, x2],同时要注意统一化,就是水平的和垂直的都是按照这个方向改。

x轴要固定向左端减小。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = + ;
struct Info {
int x1, x2, cover;
LL y;
bool operator < (const struct Info & rhs) const {
return y < rhs.y;
}
} fuck[maxn];
vector<int> vc;
struct Node {
int L, R;
int x1, x2, y;
int cover;
}seg[maxn << ];
void build(int L, int R, int cur) {
seg[cur].L = L, seg[cur].R = R;
seg[cur].x1 = vc[L], seg[cur].x2 = vc[R];
seg[cur].y = ;
seg[cur].cover = ;
if (L + == R) return;
int mid = (L + R) >> ;
build(L, mid, cur << );
build(mid, R, cur << | );
}
void pushUp(int cur) {
if (seg[cur].cover) {
seg[cur].y = vc[seg[cur].R] - vc[seg[cur].L];
} else if (seg[cur].L + == seg[cur].R) {
seg[cur].y = ;
} else {
seg[cur].y = seg[cur << ].y + seg[cur << | ].y;
}
}
void add(int be, int en, int y, int cover, int cur) {
if (seg[cur].L > en || seg[cur].R < be) return;
if (seg[cur].L >= be && seg[cur].R <= en) {
seg[cur].cover += cover;
pushUp(cur);
return;
}
add(be, en, y, cover, cur << );
add(be, en, y, cover, cur << | );
pushUp(cur);
}
void work() {
vc.clear();
vc.push_back(-inf);
int n, len = ;
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x1 == x2) {
if (y1 > y2) swap(y1, y2);
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1 - , fuck[len].cover = ;
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y2, fuck[len].cover = -;
vc.push_back(x1 - );
vc.push_back(x2);
} else {
if (x1 > x2) swap(x1, x2);
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1, fuck[len].cover = -;
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1 - , fuck[len].cover = ;
vc.push_back(x1 - );
vc.push_back(x2);
}
}
sort(vc.begin(), vc.end());
// vc.erase(unique(vc.begin(), vc.end()), vc.begin());
sort(fuck + , fuck + + len);
build(, vc.size(), );
LL ans = ;
for (int i = ; i < len; ++i) {
int x1 = lower_bound(vc.begin(), vc.end(), fuck[i].x1) - vc.begin();
int x2 = lower_bound(vc.begin(), vc.end(), fuck[i].x2) - vc.begin();
add(x1, x2, fuck[i].y, fuck[i].cover, );
ans += seg[].y * (fuck[i + ].y - fuck[i].y);
}
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}

求解区间

[L1, R1]、[L2, R2].....这样区间的,线段树的叶子节点一定要维护两个值。才算是叶子节点。就是上面所说的

主要是:因为这些区间不是连续的。

例如

要保存5、10、15、30

一般的线段树

      5、30

   5、10   15、30

  5    10    15         30

是无法得到a[4] - a[1] = 25的区间长度的。

如果你直接跑线段树,就是左右儿子的总和加上来。这样就是10 - 5 + 30 - 15 = 20

漏了一段,那一段?10--15

所以表示成

5 10 15 30

5  10            10 15  30

10 15      15 30

是一种好的选择,因为这和一般的线段树不同,一般的线段树都是连续的整数,现在是分散的。所以要这样来代表

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
#define lson L, mid, cur << 1
#define rson mid, R, cur << 1 | 1
#define root 1, all, 1
const int maxn = + ;
struct Info {
int x1, x2, cover;
LL y;
bool operator < (const struct Info & rhs) const {
return y < rhs.y;
}
} fuck[maxn];
vector<int> vc;
LL seg[maxn << ], cov[maxn << ];
void pushUp(int cur, int L, int R) {
if (cov[cur]) seg[cur] = vc[R] - vc[L];
else if (L + == R) seg[cur] = ;
else {
seg[cur] = seg[cur << ] + seg[cur << | ];
}
}
void upDate(int be, int en, int val, int L, int R, int cur) {
if (L > en || R < be) return;
if (L >= be && R <= en) {
cov[cur] += val;
pushUp(cur, L, R);
return;
}
if (L + == R) return; //必须的
int mid = (L + R) >> ;
upDate(be, en, val, lson);
upDate(be, en, val, rson); //维护两个节点
pushUp(cur, L, R);
}
void work() {
vc.clear();
vc.push_back(-inf);
int n, len = ;
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x1 == x2) {
if (y1 > y2) swap(y1, y2);
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1 - , fuck[len].cover = ;
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y2, fuck[len].cover = -;
vc.push_back(x1 - );
vc.push_back(x2);
} else {
if (x1 > x2) swap(x1, x2);
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1, fuck[len].cover = -;
++len;
fuck[len].x1 = x1 - , fuck[len].x2 = x2, fuck[len].y = y1 - , fuck[len].cover = ;
vc.push_back(x1 - );
vc.push_back(x2);
}
}
// for (int i = 1; i <= n; ++i) {
// int x1, y1, x2, y2;
// cin >> x1 >> y1 >> x2 >> y2;
// vc.push_back(x1);
// vc.push_back(x2);
// ++len;
// fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y1, fuck[len].cover = 1;
// ++len;
// fuck[len].x1 = x1, fuck[len].x2 = x2, fuck[len].y = y2, fuck[len].cover = -1;
// }
//上面注释只是普通的矩形面积交。
sort(vc.begin(), vc.end());
sort(fuck + , fuck + + len);
int all = vc.size() - ; //只能去到-1
LL ans = ;
for (int i = ; i < len; ++i) {
int x1 = lower_bound(vc.begin(), vc.end(), fuck[i].x1) - vc.begin();
int x2 = lower_bound(vc.begin(), vc.end(), fuck[i].x2) - vc.begin();
upDate(x1, x2, fuck[i].cover, root);
// cout << seg[1] << endl;
ans += seg[] * (fuck[i + ].y - fuck[i].y);
}
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
} 矩形面积交数据

HDU Atlantis 线段树 表达区间 矩形面积相交的更多相关文章

  1. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  2. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  3. HDU 1698 <线段树,区间set>

    题目连接 题意: 一条长为N的铜链子,每个结点的价值为1.有两种修改,l,r,z; z=2:表示把[l,r]区间内链子改为银质,价值为2. z=3:表示把[l,r]区间内链子改为金质,价值为3. 思路 ...

  4. 【HDU 1542】Atlantis(线段树+离散化,矩形面积并)

    求矩形面积并,离散化加线段树. 扫描线法: 用平行x轴的直线扫,每次ans+=(下一个高度-当前高度)*当前覆盖的宽度. #include<algorithm> #include<c ...

  5. HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)

    传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...

  6. POJ 1151 Atlantis(线段树-扫描线,矩形面积并)

    题目链接:http://poj.org/problem?id=1151 题目大意:坐标轴上给你n个矩形, 问这n个矩形覆盖的面积 题目思路:矩形面积并. 代码如下: #include<stdio ...

  7. 扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage

    Area Coverage Time Limit: 10000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit user ...

  8. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

  9. hdu 1255(线段树 扫描线) 覆盖的面积

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...

随机推荐

  1. Android Studio中的“favorites”和“bookmark”

    做项目难免来回查看某个文件的某个方法,某些文件可能访问率很高, 为了加快开发效率楼主推荐使用favorites (文件)bookmark (代码 行). favorites 的添加就在文件单击右键ad ...

  2. codeforces 665B B. Shopping(水题)

    题目链接: B. Shopping time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  3. 烂笔头——JAVA/JSP

    学艺不精,一些小零头放这里备忘 Object[] obj = (Object[])list.get(i);//取list的某个项目 jsp中出现out.println( )和System.out.pr ...

  4. 【CQ18高一暑假前挑战赛2】标程

    [昨晚打校赛,5个小时打完很累了,所以搞忘出题了...对不起学弟们,不过出的题都亲自写过一遍,可以保证题目和代码长度都不长,题目难度不大] [A:bush博弈] #include<bits/st ...

  5. [TJOI 2018] XOR

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5338 [算法] 首先对这棵树进行树链剖分 那么我们就将一个树上的问题转化为一个序列上 ...

  6. [AH2017/HNOI2017]抛硬币

    传送门 这个题的暴力比较好想--然后用一些组合的知识就可以变成正解了. 首先我们考虑a=b的情况.我们把扔出来的硬币看成是一个01序列,那么对于一个b获胜的序列,他在每一位都按位异或1之后必然是一个a ...

  7. 如何更快更好的写出cnblog博客?windows live writer推荐

    之前总是会羡慕网上那些技术牛人的博客都写的那么给力,后来一搜发现还是有工具可用的. 这里就推荐一款写博客的"神器",Windows Live Writer (Get It Now! ...

  8. pytest用例setup和teardown

    函数式以下两种: setup_function/teardown_function  每个用例开始和结束调用一次 setup_module/teardown_module     setup_modu ...

  9. kvm详细介绍

    KVM详解,太详细太深入了,经典 2016-07-18 19:56:38 分类: 虚拟化 原文地址:KVM详解,太详细太深入了,经典 作者:zzjlzx KVM 介绍(1):简介及安装 http:// ...

  10. 08.IdentityServer4登录中心

    08.IdentityServer4登录中心 IdentityServer就是一套Framework,实现了OAuth的授权 理解OAuth流程,学会怎么使用他 http://ruanyifeng.c ...