扫描线+图论优化学习笔记

news/2025/11/28 10:03:32/文章来源:https://www.cnblogs.com/zloi-hhq/p/19280559

虽然CPP给的标题是线段树,但是由于后面又加了道和线段树无关的题目,然后发现这个扫描线还在二维数点里面有使用,就一并完成了,所以姑且称为

扫描线+图论优化

Part 1 扫描线

oi-wiki如是说:

扫描线一般运用在图形上面,它和它的字面意思十分相似,就是一条线在整个图上扫来扫去,它一般被用来解决图形面积,周长,以及二维数点等问题。

真的是好随意的解释,但是我也不知道具体怎么说(不然我干什么要搜)

计入都说了可以解决图形面积,周长,以及二维数点等问题那么就按照这个顺序讲吧

面积

P5490 【模板】扫描线 & 矩形面积并

只好解决矩形面积了

扫描线处理大部分问题,都是将一维通过扫描线枚举得到,另一维通过数据结构进行维护。

那么具体怎么处理?

输入每一个矩形,我们都可以得到一个矩形的四点,由于范围很大,我们明显需要离散化来处理每一个用数据结构存储的点。

我们通过扫描线的思路,把一个矩形拆成两条线,一个+1,一个-1,分别表示添加一条边或者减少一条边即可。

我们按照扫描线处理的一维排序,按照顺序加入线段树,处理即可。

需要注意的点是我们在线段树里面记录的不是点,而是两点之间的区间,这样才可以得到每一组的答案。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#define int long long
using namespace std;
const int N=1e5+5;
int n,tmp[N*2],cnt;
struct P{int l,r,y,v;
}li[N*2];
bool cmp(P a,P b){return a.y<b.y;
}
struct ST{int c[N<<4],tag[N<<4],len[N<<4];#define ls p<<1#define rs p<<1|1void pushup(int p){if(tag[p])c[p]=len[p];else c[p]=c[ls]+c[rs];}void build(int p,int l,int r){len[p]=tmp[r+1]-tmp[l];if(l==r)return;int mid=l+r>>1;build(ls,l,mid),build(rs,mid+1,r);}void change(int p,int l,int r,int L,int R,int v){if(l>=L&&r<=R){tag[p]+=v;pushup(p);return;}int mid=l+r>>1;if(mid>=L)change(ls,l,mid,L,R,v);if(mid<R)change(rs,mid+1,r,L,R,v);pushup(p);}
}tr;
signed main(){cin>>n;cnt=0;for(int i=1,x,y,xx,yy;i<=n;i++){scanf("%lld%lld%lld%lld",&x,&y,&xx,&yy);li[i]={x,xx,y,1};li[i+n]={x,xx,yy,-1};tmp[++cnt]=x;tmp[++cnt]=xx;}sort(li+1,li+2*n+1,cmp);sort(tmp+1,tmp+cnt+1);cnt=unique(tmp+1,tmp+cnt+1)-tmp-1;tr.build(1,1,cnt-1);for(int i=1;i<=2*n;i++){li[i].l=lower_bound(tmp+1,tmp+cnt+1,li[i].l)-tmp;li[i].r=lower_bound(tmp+1,tmp+cnt+1,li[i].r)-tmp;}int ans=0;for(int i=1;i<=2*n;i++){if(i!=1)ans+=tr.c[1]*(li[i].y-li[i-1].y);tr.change(1,1,cnt-1,li[i].l,li[i].r-1,li[i].v);}cout<<ans;return 0;
}

周长

Picture

还是按照扫描线做法处理

直接用线段树记录目前这条线上分了几段边,然后计入另一维长度的贡献

但是这样只记录了一边,比较赖的做法是也给另一边跑一次,这样更加简单。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#define int long long
using namespace std;
int n,ma;
struct L{int l,r,x,f;
}a[200005],b[200005];
bool cmp(L a,L b){return a.x<b.x;
}
struct ST{struct P{int s,l,r;}c[100005];int tag[100005],len[100005];#define ls p<<1#define rs p<<1|1void pushup(int p){if(tag[p]){c[p]={1,1,1};}else if(len[p]==1){c[p]={0,0,0};}else {c[p].s=c[ls].s+c[rs].s;if(c[ls].r&&c[rs].l)c[p].s--;c[p].l=c[ls].l,c[p].r=c[rs].r;}}void build(int p,int l,int r){tag[p]=0;len[p]=r-l+1;c[p]={0,0,0};if(l==r)return;int mid=l+r>>1;build(ls,l,mid),build(rs,mid+1,r);}void change(int p,int l,int r,int L,int R,int v){if(l>=L&&r<=R){tag[p]+=v;pushup(p);return ;}int mid=l+r>>1;if(mid>=L)change(ls,l,mid,L,R,v);if(mid<R)change(rs,mid+1,r,L,R,v);pushup(p);}
}tr;
int solve(L p[]){int ans=0;sort(p+1,p+2*n+1,cmp);tr.build(1,1,20005);for(int i=1;i<=2*n;i++){if(i!=1)ans+=(p[i].x-p[i-1].x)*tr.c[1].s;tr.change(1,1,20005,p[i].l,p[i].r-1,p[i].f);}return ans;
}
signed main(){scanf("%lld",&n);if(n==0)printf("0");else {for(int i=1,x,y,xx,yy;i<=n;i++){scanf("%lld%lld%lld%lld",&x,&y,&xx,&yy);x+=10001;y+=10001;xx+=10001;yy+=10001;a[i]={x,xx,y,1};b[i]={y,yy,x,1};a[i+n]={x,xx,yy,-1};b[i+n]={y,yy,xx,-1};}}cout<<2*(solve(a)+solve(b));return 0;
}

二维数点

P2163 [SHOI2007] 园丁的烦恼

比较常见的类型

也是按照一维扫描,一维数据结构来实现

这一次按照顺序扫描,实际上是类似前缀和的操作,要减去左边的线的贡献

这样就可以得到了

代码:

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=5e5+5;
int n,m,x[N],y[N],tmpx[N*3],tmpy[N*3],cntx,cnty,ans[N];
vector<int> e1[N],e2[N],e3[N];
int lowbit(int x){return x&-x;
}
struct BT{int c[3*N];void add(int x,int y){for(int i=x;i<=cnty;i+=lowbit(i))c[i]+=y;}int query(int x){int ans=0;for(int i=x;i>=1;i-=lowbit(i))ans+=c[i];return ans;}
}bit;
struct P{int x,y,xx,yy;
}a[N];
signed main(){cin>>n>>m;for(int i=1;i<=n;i++)cin>>x[i]>>y[i];for(int i=1;i<=n;i++)tmpx[++cntx]=x[i],tmpy[++cnty]=y[i];for(int i=1;i<=m;i++){cin>>a[i].x>>a[i].y>>a[i].xx>>a[i].yy;a[i].x--,a[i].y--;tmpx[++cntx]=a[i].x;tmpx[++cntx]=a[i].xx;tmpy[++cnty]=a[i].y;tmpy[++cnty]=a[i].yy;}int tmp;sort(tmpx+1,tmpx+cntx+1);tmp=unique(tmpx+1,tmpx+cntx+1)-tmpx-1;cntx=tmp;sort(tmpy+1,tmpy+cnty+1);tmp=unique(tmpy+1,tmpy+cnty+1)-tmpy-1;cnty=tmp;for(int i=1;i<=n;i++)x[i]=lower_bound(tmpx+1,tmpx+cntx+1,x[i])-tmpx;for(int i=1;i<=n;i++)y[i]=lower_bound(tmpy+1,tmpy+cnty+1,y[i])-tmpy;for(int i=1;i<=n;i++)e1[x[i]].push_back(y[i]);for(int i=1;i<=m;i++)a[i].x=lower_bound(tmpx+1,tmpx+cntx+1,a[i].x)-tmpx;for(int i=1;i<=m;i++)a[i].xx=lower_bound(tmpx+1,tmpx+cntx+1,a[i].xx)-tmpx;for(int i=1;i<=m;i++)a[i].y=lower_bound(tmpy+1,tmpy+cnty+1,a[i].y)-tmpy;for(int i=1;i<=m;i++)a[i].yy=lower_bound(tmpy+1,tmpy+cnty+1,a[i].yy)-tmpy;for(int i=1;i<=m;i++)e2[a[i].x].push_back(i);for(int i=1;i<=m;i++)e3[a[i].xx].push_back(i);for(int i=1;i<=cntx;i++){for(int j=0;j<e1[i].size();j++)bit.add(e1[i][j],1);for(int j=0;j<e2[i].size();j++)ans[e2[i][j]]-=bit.query(a[e2[i][j]].yy)-bit.query(a[e2[i][j]].y);for(int j=0;j<e3[i].size();j++)ans[e3[i][j]]+=bit.query(a[e3[i][j]].yy)-bit.query(a[e3[i][j]].y);}for(int i=1;i<=m;i++){cout<<ans[i]<<endl;}return 0;
}

P1972 [SDOI2009] HH的项链

依然离线

考虑按照顺序处理一维,即扫描线,另一维靠数据结构

我们记录上一次出现的位置,将贡献删除即可达成离线处理的操作’

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1000005],pre[1000005],q,ans[1000005];
int read(){char c=getchar();while(c>'9'||c<'0')c=getchar();int x=0;while(c<='9'&&c>='0')x=x*10+c-48,c=getchar();return x;
}
int lowbit(int x){return x&-x;
}
struct P{int l,r,id;bool friend operator<(P a,P b){return a.r<b.r;}
}b[1000005];
struct BT{int c[1000005];void add(int x,int y){for(int i=x;i<=n;i+=lowbit(i))c[i]+=y;}int query(int x){int ans=0;for(int i=x;i>=1;i-=lowbit(i))ans+=c[i];return ans;}int query(int l,int r){return query(r)-query(l-1);}
}bit;
signed main(){n=read();for(int i=1;i<=n;i++)a[i]=read();q=read();for(int i=1;i<=q;i++){b[i].l=read();b[i].r=read();b[i].id=i;}sort(b+1,b+q+1);int w=0;for(int i=1;i<=q;i++){while(w<b[i].r){w++;if(pre[a[w]])bit.add(pre[a[w]],-1);bit.add(w,1);pre[a[w]]=w;}ans[b[i].id]=bit.query(b[i].l,b[i].r);}for(int i=1;i<=q;i++){printf("%lld\n",ans[i]);}return 0;
}

这样扫描线就弄完了

Part 2 图论优化

常规的建图方式可能并不能满足所有需求,比如跑最短路时,时间复杂度与边数是息息相关的。

但是有一些比较毒瘤的题目,建边存在规律

线段树优化建图

一些需要一个点连多个点以及多个点连一个点,连的次数太多明显会有问题,所有可以考虑线段树优化建图。

原理很简单,把几个节点放在一起,搞一个线段树即可。

每个非叶子节点有两个点,一个向上连接,一个向下连接,这样就可以保证树的单向性,根据不同情况可以选择不同的方案连接,并在此之前提前处理出线段树建边。

例题: CF786B Legacy

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,s,cnt,in[400005],out[400005],dis[400005],hhq;
vector<pair<int,int>> e[400005];
bool vis[400005];
struct ST{#define ls p<<1#define rs p<<1|1void build(int p,int l,int r){if(l==r){in[p]=out[p]=l;return;}in[p]=++cnt,out[p]=++cnt;int mid=l+r>>1;build(ls,l,mid),build(rs,mid+1,r);e[out[p]].push_back({out[ls],0});e[out[p]].push_back({out[rs],0});e[in[ls]].push_back({in[p],0});e[in[rs]].push_back({in[p],0});}void change(int p,int l,int r,int L,int R,int v,int w,bool f){if(l>=L&&r<=R){if(f)e[in[p]].push_back({v,w});else e[v].push_back({out[p],w});return;}int mid=l+r>>1;if(mid>=L)change(ls,l,mid,L,R,v,w,f);if(mid<R)change(rs,mid+1,r,L,R,v,w,f);}
}seg;
struct P{int x,dis;bool friend operator<(P a,P b){return a.dis>b.dis;}
};
void dij(){memset(dis,0x3f,sizeof(dis));priority_queue<P> q;q.push({s,0});dis[s]=0;while(!q.empty()){P u=q.top();q.pop();if(vis[u.x])continue;vis[u.x]=1;for(auto tmp:e[u.x]){int v=tmp.first,w=tmp.second;if(w+u.dis<dis[v]){dis[v]=w+u.dis;q.push({v,dis[v]});}}}
}
signed main(){cin>>n>>q>>s;cnt=n;seg.build(1,1,n);for(int i=1,op,v,l,r,w;i<=q;i++){cin>>op>>v>>l;if(op!=1)cin>>r;cin>>w;if(op==1)e[v].push_back({l,w});else if(op==2)seg.change(1,1,n,l,r,v,w,0);else seg.change(1,1,n,l,r,v,w,1);}dij();for(int i=1;i<=n;i++){if(dis[i]>=1e18)cout<<-1<<' ';else cout<<dis[i]<<' ';}return 0;
}

前后缀优化建图

有一些题目依然毒瘤,像是有 \(n\) 个点,每一个都能够互相到达,然后还要求最短路径

那么如果建边有明显规律,可以考虑前后缀建图,比较套路的,如果长度为两点之差,那么直接相邻建差值长度边(只是栗子)

例题: AT_abc232_g [ABC232G] Modulo Shortest Path

我们跳出来需要a,进去需要b

因为要模,所有不好直接搞

我们发现每次建边有两种情况,一种是模了,一种是没有模

我们发现把b排序以后就可以对每个点二分出带模不带模的分界线

然后考虑建边,直接分三层,一层为原始点,一层向左,一层向右,然后按照二分的点连边,返回时再记录b

这样图就建完了

但是有问题,这题卡spfa,而a-m是负边权,跑不了

只能把b前移作差,由于已经排序,所有一定正,非常巧

代码:

#include<bits/stdc++.h>
using namespace std;
int n,mod,tmp[200005],dis[600005];
bool vis[600005];
struct P{int a,b,id;
}c[200005];
bool cmp(P a,P b){return a.b<b.b;
}
struct Q{int x,dis;bool friend operator<(Q a,Q b){return a.dis>b.dis;}
};
vector<pair<int,int>> e[600005];
int dij(int s,int en){priority_queue<Q> q;memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));dis[s]=0;q.push({s,dis[s]});while(!q.empty()){Q u=q.top();q.pop();if(vis[u.x])continue;if(u.x==en)return u.dis;vis[u.x]=1;for(auto tmp:e[u.x]){int v=tmp.first,w=tmp.second;if(dis[v]>u.dis+w){dis[v]=u.dis+w;q.push({v,dis[v]});}}}
}
signed main(){cin>>n>>mod;for(int i=1;i<=n;i++)cin>>c[i].a;for(int i=1;i<=n;i++)cin>>c[i].b;for(int i=1;i<=n;i++)c[i].id=i;sort(c+1,c+n+1,cmp);for(int i=1;i<=n;i++){e[i+n].push_back({i,c[i].b});e[i+2*n].push_back({i,0});tmp[c[i].id]=i;}for(int i=2;i<=n;i++)e[i+n].push_back({i+n-1,0});for(int i=1;i<n;i++)e[i+2*n].push_back({i+2*n+1,c[i+1].b-c[i].b});for(int i=1;i<=n;i++){int l=1,r=n;while(l<=r){int mid=l+r>>1;if(c[mid].b+c[i].a>=mod)r=mid-1;else l=mid+1;}r++;if(r!=1)e[i].push_back({r-1+n,c[i].a});if(r!=n+1)e[i].push_back({r+2*n,c[i].a+c[r].b-mod});}cout<<dij(tmp[1],tmp[n]);return 0;
}

完结撒花

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/979330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年耐用的集束电缆/矿物质防火电缆厂家最新用户好评榜

2025年耐用的集束电缆/矿物质防火电缆厂家用户好评榜行业背景与市场趋势随着全球能源需求的持续增长和基础设施建设的加速推进,电线电缆行业迎来了前所未有的发展机遇。特别是在"双碳"目标背景下,高效、安…

2025年优质的淋浴房配件厂家最新热销排行

2025年优质的淋浴房配件厂家热销排行行业背景与市场趋势随着人们生活品质的不断提升,卫浴空间作为家居生活的重要组成部分,其舒适度和美观度越来越受到消费者的重视。淋浴房作为现代卫浴空间的核心元素,其配件质量直…

重点高中退休教师授课培训机构,2025年高中培训机构权威评估指南

在高中学习的关键阶段,每一位学子都渴望找到那个能助力自己突破瓶颈、实现飞跃的特训班。无论是面对压轴题的挑战,还是中档题的困扰,选择一家靠谱的特训机构都至关重要。在众多选择中,选择有重点高中退休教师授课培…

番茄工作法计时器:专注力与效率的简洁管理工具

在信息爆炸、注意力分散的时代,如何保持高效专注成为许多人面临的挑战。番茄工作法计时器正是基于这一需求应运而生的经典时间管理工具。它通过一种简单而强大的机制,帮助用户将精力集中在当前任务上,从而显著提升工…

2025精密塑胶模具厂家测评大盘点

2025精密塑胶模具厂家测评大盘点!在选择精密塑胶模具厂家时,建议从以下几个维度进行考量:首先关注企业的专业领域与自身需求是否匹配,比如是否专注于特定行业或产品类型;其次可以考察其技术装备与研发能力,这关系…

2025数控加工中心机床厂家实力榜单

在数控加工中心机床领域,一批专注技术研发、深耕细分场景的实力厂家正凭借扎实的产品实力和精准的服务脱颖而出。本次榜单聚焦 10 家知名度实力出众的企业,涵盖数控加工中心机床厂家直销模式践行者与数控加工中心机床…

2025艺术涂料加盟必看!荷兰蔻帝帮扶政策封神,万元补贴+3公里独家保护

艺术涂料加盟水很深?选对品牌让你赢在起跑线! 想在2025年投身艺术涂料行业,却担心加盟风险?不知道如何选择靠谱品牌?艺术涂料市场正以年均25%的增速扩张,但品牌间的扶持政策千差万别。今天为你揭秘那些真正为加盟…

世界时间仪表盘:一站式全球时间管理解决方案

在全球化日益深入的今天,与分布在世界各地的团队、客户或伙伴协作已成为常态。高效协作的首要前提,是清晰地掌握不同地区的时间。“世界时间仪表盘”正是为此而生的高效工具,它通过简洁直观的界面,让全球时间一目了…

2025比较好的英国留学中介

2025比较好的英国留学中介一、2025年选择英国留学中介的常见问题解答作为从业十二年的国际教育规划师,我经常被学生和家长询问如何在2025年选择一家可靠的英国留学中介。许多人在搜索引擎上会输入“英国留学中介哪家靠…

2025权威榜单:进口艺术涂料品牌全攻略,这些品牌获欧盟SGS认证,南方回南天也不怕!

2025权威榜单:进口艺术涂料品牌全攻略,这些品牌获欧盟SGS认证,南方回南天也不怕!别再为墙面潮湿发愁了,这些进口艺术涂料让你的家清爽如新每到南方回南天,墙面"冒汗"、发霉、起皮就成了不少家庭的噩梦…

2025年11月真空袋厂家推荐榜单:知名企业列表与选择指南

在包装行业不断升级的今天,真空袋作为食品、日化、电子等多个领域的重要包装材料,其质量与性能直接影响产品保鲜与品牌形象。许多采购商、品牌方在选择真空袋厂家时,常面临供应商资质参差不齐、交付周期不稳定、产品…

2025年口碑好的养殖温室大棚厂家最新推荐排行榜

2025年口碑好的养殖温室大棚厂家推荐排行榜行业背景与市场趋势随着现代农业技术的快速发展和规模化养殖需求的增加,养殖温室大棚行业近年来呈现出蓬勃发展的态势。2025年,受政策支持、技术进步和市场需求三重驱动,养…

墙面翻新别瞎选!2025涂料十大品牌权威榜,荷兰蔻帝防霉抗污封神

墙面翻新别瞎选!2025涂料十大品牌权威榜,荷兰蔻帝防霉抗污封神 墙面一换,老房立马变新家!选对涂料是关键 家里墙面发霉、掉皮、有污渍,看着就心烦?想要翻新却不知该选什么涂料?2025年的涂料市场早已有了全新升级…

TabControl的bug

删除页有bug,有时候是会删除错误,同事和朋友都验证过int index = tabControl1.SelectedIndex; tabControl1.TabPages.RemoveAt(index); 改成int index = tabControl1.SelectedIndex;var tabpage = tabControl1.TabP…

信创背景下, DevOps体系中制品库的全生命周期安全管控

制品库作为DevOps核心资产仓库,其安全管控对关键行业至关重要。优质制品管理平台需具备信创全栈兼容、制品全生命周期安全管控、强合规性及生态融合能力,且经权威认证背书。企业选型应结合业务需求、安全合规等因素综…

2025隔音降噪厂家与隔音房厂家实力榜单

2025隔音降噪厂家与隔音房厂家实力榜单。在现代城市建设与运营过程中,工业设备、公共交通及建筑设施产生的噪声,已成为影响生活品质与工作环境的重要因素。噪声治理产品具备多频段降噪能力,可针对低频设备震动噪声、…

2025年11月真空袋厂家推荐:全面评测数据与实用决策参考

在寻找真空袋厂家的过程中,用户可能面临多种需求场景,例如食品企业需要符合安全标准的包装材料,电商品牌寻求高性价比的定制服务,或者工业用户关注产品的耐用性和特殊性能。真空袋作为包装行业的重要分支,其市场需…

如何选择优质护手霜?2025十大精选护手霜品牌深度解析!强效滋润修复呵护手部肌肤

厨房内,刚洗完油腻碗筷的王阿姨,手背瞬间泛起红血丝,指节老茧粗糙如砂,涂过普通护手霜的双手遇水后更显干涩紧绷;写字楼里,李女士敲击键盘的指尖已冒出细密干纹,秋冬空调房的干燥让虎口处反复脱皮;接送孩子的张…

2025年评价高的阶梯式养鸡设备热门厂家推荐榜单

2025年评价高的阶梯式养鸡设备热门厂家推荐榜单行业背景与市场趋势随着中国畜牧业的快速发展,养鸡设备行业正迎来前所未有的机遇。2024年数据显示,中国家禽养殖业市场规模已突破5000亿元,其中自动化养殖设备占比逐年…

2025俄罗斯电商选品软件:俄罗斯电商选品工具测评

2025俄罗斯电商选品软件:俄罗斯电商选品工具测评!在俄罗斯电商市场竞争日趋激烈的 2025 年,选品的精准度直接决定卖家的市场竞争力,而专业的俄罗斯电商选品软件则成为提升选品效率的核心助力。对于中国卖家而言,选择…