Intersecting Rectangles
大致意思是给定n个矩形,问是否会存在相交
直接套扫描线
区分左边和右边,如果在还没抵消时发现区间已经有数值,说明会相交
AC Code:
// http://115.157.200.87/front/problem?problemId=1202
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = static_cast<const int>(4e5 + 100);
struct VerticalLine {
int x, y1, y2, type;
VerticalLine() = default;
VerticalLine(int x, int y1, int y2, int type) : x(x), y1(y1), y2(y2), type(type) {}
bool operator<(VerticalLine const &o) const { return x < o.x; }
};
class TreeArray {
public:
long long treeArray[maxn]{};
inline long lowBit(long x) {
return x & (-x);
}
void add(long treeIndex, long value) {
while (treeIndex <= maxn) {
treeArray[treeIndex] += value;
treeIndex += lowBit(treeIndex);
}
}
long long sum(long x) {
long long ans = 0;
while (x != 0) {
ans += treeArray[x];
x -= lowBit(x);
}
return ans;
}
long long query(long l, long r) {
if (l > r) {
return 0;
}
return sum(r) - sum(l - 1);
}
} treeArray;
vector<int> ys;
vector<VerticalLine> queries;
int n;
bool solve() {
for (auto q: queries) {
long l = lower_bound(ys.begin(), ys.end(), q.y1) - ys.begin() + 1;
long r = lower_bound(ys.begin(), ys.end(), q.y2) - ys.begin() + 1;
if (q.type == 1) {
if (treeArray.query(l, r) > 0)
return true;
treeArray.add(l, 1);
treeArray.add(r, 1);
} else {
treeArray.add(l, -1);
treeArray.add(r, -1);
if (treeArray.query(l, r) > 0)
return true;
}
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
int x1, y1, x2, y2;
for (int i = 0; i < n; ++i) {
cin >> x1 >> y1 >> x2 >> y2;
queries.emplace_back(x1, y1, y2, 1);
queries.emplace_back(x2, y1, y2, -1);
ys.push_back(y1);
ys.push_back(y2);
}
sort(ys.begin(), ys.end());
sort(queries.begin(), queries.end());
if (solve())
cout << '1';
else cout << '0';
return 0;
}
Rectangles
题目大意:求重叠奇数次区域的面积
这题麻烦一点,主要是线段树一开始写错了 调bug调了很久。。。
对每条边 先计算面积 然后进行区间异或
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = static_cast<const int>(4e5 + 100);
vector<int> ys, xs;
namespace SegmentTree {
int const maxn = static_cast<const int>(5e5 + 5);
struct Node {
int l, r;
ll value, realLength;
bool lazy;
void _xor() {
value = realLength - value;
}
} segTree[maxn * 3];
void set(int i) {
segTree[i]._xor();
segTree[i].lazy ^= true;
}
void push_up(int i) { segTree[i].value = segTree[i << 1].value + segTree[(i << 1) | 1].value; }
void push_down(int i) {
if (!segTree[i].lazy) return;
set(i << 1), set(i << 1 | 1);
segTree[i].lazy = false;
}
/**
* segTree[i].realLength = ys[r+1] - ys[l]
*
* @param i 1
* @param l 0-based, inclusive.
* @param r 0-based, inclusive.
*/
void build(int i, int l, int r) {
segTree[i].l = l;
segTree[i].r = r;
if (l == r) {
segTree[i].realLength = ys[l + 1] - ys[l];
return;
}
// if (l == r) {
// segTree[i].realLength = -1;
// return;
// }
int mid = (l + r) / 2;
build(i << 1, l, mid);
build((i << 1) | 1, mid + 1, r);
segTree[i].realLength = segTree[i << 1].realLength + segTree[i << 1 | 1].realLength;
// if (segTree[i << 1].realLength == 0) {
// segTree[i].realLength = ys[r] - ys[l];
// } else segTree[i].realLength = segTree[i << 1].realLength + segTree[i << 1 | 1].realLength;
}
/**
* interval update.
*
* @param i 1
* @param l 0-based, inclusive
* @param r 0-based, inclusive.
* @param val The value.
*/
void update(int i, long l, long r) {
// if (i == 6)
// cout << "pause" << endl;
if (segTree[i].l >= l && segTree[i].r <= r) {
set(i);
return;
}
push_down(i);
int mid = (segTree[i].l + segTree[i].r) / 2;
if (l <= mid) update(i << 1, l, r);
if (r > mid) update((i << 1) | 1, l, r);
push_up(i);
}
}
struct VerticalLine {
int x, y1, y2, type;
VerticalLine() = default;
VerticalLine(int x, int y1, int y2, int type) : x(x), y1(y1), y2(y2), type(type) {}
bool operator<(VerticalLine const &o) const { return x < o.x; }
};
vector<VerticalLine> queries;
int n;
ll solve() {
ll res = 0;
ll lastX = queries[0].x;
for (auto q: queries) {
long l = lower_bound(ys.begin(), ys.end(), q.y1) - ys.begin();
long r = lower_bound(ys.begin(), ys.end(), q.y2) - ys.begin();
// if (q.type == 1) {
// } else {
//
// }
res += abs(lastX - q.x) * SegmentTree::segTree[1].value;
SegmentTree::update(1, l, r - 1);
// cout << "curr " << q.y1 << " " << q.y2 << " (l,r): " << l << " " << r << " " << SegmentTree::segTree[1].value
// << endl;
lastX = q.x;
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
int x1, y1, x2, y2;
for (int i = 0; i < n; ++i) {
cin >> x1 >> y1 >> x2 >> y2;
queries.emplace_back(x1, y1, y2, 1);
queries.emplace_back(x2, y1, y2, -1);
ys.push_back(y1);
ys.push_back(y2);
xs.push_back(x1);
xs.push_back(x2);
}
sort(ys.begin(), ys.end());
sort(queries.begin(), queries.end());
SegmentTree::build(1, 0, ys.size() - 2);
cout << solve() << endl;
return 0;
}
线段树模板
class SegmentTree {
public:
struct Node {
int l, r;
ll value, realLength;
bool lazy;
//todo: remove this if necessary
void _xor() { value = realLength - value; }
} segTree[maxn * 3];
//TODO: modify this.
void set(int i) {
segTree[i]._xor();
segTree[i].lazy ^= true;
}
//todo: modify this
void push_up(int i) { segTree[i].value = segTree[i << 1].value + segTree[(i << 1) | 1].value; }
void push_down(int i) {
if (!segTree[i].lazy) return;
set(i << 1), set(i << 1 | 1);
segTree[i].lazy = false;
}
/**
*
* @param i 1
* @param l 0-based, inclusive.
* @param r 0-based, inclusive.
*/
void build(int i, int l, int r) {
segTree[i].l = l;
segTree[i].r = r;
if (l == r) {
segTree[i].realLength = ys[l + 1] - ys[l];
return;
}
int mid = (l + r) / 2;
build(i << 1, l, mid);
build((i << 1) | 1, mid + 1, r);
segTree[i].realLength = segTree[i << 1].realLength + segTree[i << 1 | 1].realLength;
}
/**
* interval update.
*
* @param i 1
* @param l 0-based, inclusive
* @param r 0-based, inclusive.
* @param val The value.
*/
void update(int i, long l, long r) {
if (segTree[i].l >= l && segTree[i].r <= r) {
set(i);
return;
}
push_down(i);
int mid = (segTree[i].l + segTree[i].r) / 2;
if (l <= mid) update(i << 1, l, r);
if (r > mid) update((i << 1) | 1, l, r);
push_up(i);
}
ll query(int i, int l, int r) {
if (l <= segTree[i].l && segTree[i].r <= r)
return segTree[i].value; //完全被包含的区间直接返回区间和
if (r < segTree[i].l || segTree[i].r < l)
return 0; //如果区间和查找区间没有交集,则直接返回0
if (segTree[i].lazy)
push_down(i); //这里要写在判断是否与查找区间有交集后面
return query(i << 1, l, r) + query(i << 1 | 1, l, r);
}
};