如果不考虑奇偶性,其实就是扫描线的板子。
考虑如何处理奇偶:
首先在线段树存两个变量 \(len_1\) 以及 \(len_2\),分别表示奇长度和偶长度。再用 \(sum\) 记录当前两个端点之间被覆盖了多少次。
然而我们无法直接获得每一个子区间的具体覆盖数目。所以从奇偶性的特点方面入手。
假设当前区间被覆盖了奇数次,那么:
\(len_2 = 子区间len_1\)
\(len_1 = 子区间len_2 + 可能未被覆盖到的长度\)
\(len_1\)无法直接求,但是可以用总区间长度减去\(len_2\)得到。
代码:
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
#define y1 abdbsdhuhdwiuoh
#define int long long
template <class T>
inline T read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c= getchar(); }
a = x * s;
return a;
}
int n;
struct Line{
int x, y, h, flag;
} L[N << 1];
int X[N << 1]; // 离散化坐标
struct Segment_tree{
struct node{
int sum, len1, len2;
} t[N << 4]; // 多乘一个2
#define lson (o<<1)
#define rson (o<<1|1)
inline void pushup(int o, int l, int r){
if(t[o].sum){
if(t[o].sum){
if(t[o].sum % 2 == 1){
if(l == r){
t[o].len1 = X[r + 1] - X[l];
t[o].len2 = 0;
}
else{
t[o].len2 = t[lson].len1 + t[rson].len1;
t[o].len1 = X[r + 1] - X[l] - t[o].len2;
}
}
else{
if(l == r){
t[o].len2 = X[r + 1] - X[l];
t[o].len1 = 0;
}
else{
t[o].len1 = t[lson].len1 + t[rson].len1;
t[o].len2 = X[r + 1] - X[l] - t[o].len1;
}
}
}
}
else{
if(l == r) t[o].len1 = t[o].len2 = 0; // 不特判的话要多加一层
else {
t[o].len1 = t[lson].len1 + t[rson].len1;
t[o].len2 = t[lson].len2 + t[rson].len2;
}
}
return ;
}
void build(int o, int l, int r){
t[o].sum = t[o].len1 = t[o].len2 = 0;
if(l == r) return ;
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(o, l, r);
return ;
}
void update(int o, int l, int r, int L, int R, int k){
if(X[l] >= R || X[r + 1] <= L) return ; // 端点相等也是不够的。因为表示的是右侧一段区间,端点没有意义。
if(X[l] >= L && X[r + 1] <= R){
t[o].sum += k;
pushup(o, l, r);
return ;
}
int mid = l + r >> 1;
update(lson, l, mid, L, R, k);
update(rson, mid + 1, r, L, R, k);
pushup(o, l, r);
return ;
}
} tree;
signed main(){
read(n);
for(int i = 1; i <= n; i++){
int x1, y1, x2, y2;
read(x1), read(y1), read(x2), read(y2);
L[i * 2 - 1] = (Line){x1, x2, y1, 1};
L[i * 2] = (Line){x1, x2, y2, -1};
X[i * 2 - 1] = x1;
X[i * 2] = x2;
}
n <<= 1ll;
sort(X + 1, X + n + 1);
int tot = unique(X + 1, X + n + 1) - X - 1;
sort(L + 1, L + n + 1, [](Line a, Line b){
return a.h < b.h;
});
tree.build(1, 1, tot - 1);
int ans1 = 0, ans2 = 0;
for(int i = 1; i < n; i++){
tree.update(1, 1, tot - 1, L[i].x, L[i].y, L[i].flag);
ans1 += tree.t[1].len1 * (L[i+1].h - L[i].h);
ans2 += tree.t[1].len2 * (L[i + 1].h - L[i].h);
}
cout << ans1 << endl << ans2 << endl;
return 0;
}
标签:奇偶,覆盖,int,mid,long,蓝桥,2020,len,define
From: https://www.cnblogs.com/wondering-world/p/18050385