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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理