4e5大小的线段树来喽!怎么,都RE了? Luogu P3875 [TJOI2010]被污染的河流
P3875 [TJOI2010]被污染的河流 题解
本来是为了改昨天的题,发现扫描线基本上都忘了,打算找个扫描线练练手,结果打的有来有回的。
解析
污染区域是以河流为中线的一块矩形,可能生病的社区数量就是这些矩形的面积并。
很显然是扫描线,线段树维护。
存储每个矩形左,右边界,左边界赋1,右边界赋-1 ,把线段排序,再依次处理每一条线段。
整体来说挺板子的,需要注意一些小细节。
河流起始位置和结束位置的坐标不一定先左后右,先下后上,所以要swap一下。
x值相等时,河流为纵向流向,左边界的x值为 x - 1,右边界的x值为 x + 1。
y值相等时,河流为横向流向,左,右边界的yl(下方的端点)值为 y - 1,yl(上方的端点)值为 y + 1。
因为有 - 1 和 + 1 的操作,所以端点会出现值为 0 或 1000001 的情况,线段树初始化的时候要注意。
最重要的是,4e5 大小的线段树会RE,所以开大一点。
Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 1e4 + 10, MAXM = 2e5 + 10;
int n, sum, maxr;
struct Line{
int x;
int yh, yl;
int sit;
}line[MAXM << 1];
inline bool cmp(const Line &a, const Line &b){
return a.x < b.x;
}
struct Segment_Tree{
struct Tree{
int l, r;
int len;
int cnt;
}tr[MAXM << 2];
inline int lson(int rt){
return rt << 1;
}
inline int rson(int rt){
return rt << 1 | 1;
}
inline void Pushup(int rt){
if(tr[rt].cnt)
tr[rt].len = tr[rt].r - tr[rt].l + 1;
else
tr[rt].len = tr[lson(rt)].len + tr[rson(rt)].len;
}
void Build(int rt, int l, int r){
tr[rt].l = l;
tr[rt].r = r;
tr[rt].len = 0;
tr[rt].cnt = 0;
if(l == r)
return;
int mid = (l + r) >> 1;
Build(lson(rt), l, mid);
Build(rson(rt), mid + 1, r);
}
void Update(int rt, int l, int r, int data){
if(tr[rt].l >= l && tr[rt].r <= r){
tr[rt].cnt += data;
Pushup(rt);
return;
}
int mid = (tr[rt].l + tr[rt].r) >> 1;
if(l <= mid) Update(lson(rt), l, r, data);
if(r > mid) Update(rson(rt), l, r, data);
Pushup(rt);
}
}S;
inline int read(){
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
int main(){
n = read();
for(register int i = 1; i <= n; i++){
int x1, y1, x2, y2;
x1 = read(), y1 = read(), x2 = read(), y2 = read();
if(x1 > x2) swap(x1, x2);
if(y1 > y2) swap(y1, y2);
if(x1 == x2){
line[(i << 1) - 1].x = x1 - 1, line[(i << 1)].x = x2 + 1;
line[(i << 1) - 1].yl = line[(i << 1)].yl = y1;
line[(i << 1) - 1].yh = line[(i << 1)].yh = y2;
line[(i << 1) - 1].sit = 1;
line[(i << 1)].sit = -1;
}
else if(y1 == y2){
line[(i << 1) - 1].x = x1, line[(i << 1)].x = x2;
line[(i << 1) - 1].yl = line[(i << 1)].yl = y1 - 1;
line[(i << 1) - 1].yh = line[(i << 1)].yh = y2 + 1;
line[(i << 1) - 1].sit = 1;
line[(i << 1)].sit = -1;
}
}
n <<= 1;
sort(line + 1, line + 1 + n, cmp);
S.Build(1, 0, 100001);
for(register int i = 1; i < n; i++){
S.Update(1, line[i].yl, line[i].yh - 1, line[i].sit);
sum += S.tr[1].len * (line[i + 1].x - line[i].x);
}
printf("%d\n", sum);
return 0;
}
以下为博客签名,与博文无关。
只要你们不停下来,那前面就一定有我。所以啊,不要停下来~
本文来自博客园,作者:TSTYFST,转载请注明原文链接:https://www.cnblogs.com/TSTYFST/p/16581418.html