[题解/模板]扫描线
Posted superminivan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解/模板]扫描线相关的知识,希望对你有一定的参考价值。
luogu_P1856矩形周长
#include<bits/stdc++.h> #define ls (x<<1) #define rs (x<<1|1) //#define mid (l+r>>1) using namespace std; const int maxn=5009; const int maxm=10009; int n,ans; struct square int xa,xb,ya,yb; r[maxn]; int hsh[maxn<<1],cnt; struct line int l,r,h,f; bool operator <(const line&a)const return h<a.h||h==a.h &&f>a.f; e[maxn<<1]; struct node int sum,tag; t[maxm<<2]; void upd(int x,int l,int r) if(t[x].tag)t[x].sum=hsh[r+1]-hsh[l]; else if(l==r)t[x].sum=0; else t[x].sum=t[ls].sum+t[rs].sum; void change(int x,int l,int r,int L,int R,int f) if(L<=l && r<=R) t[x].tag+=f; else int mid=(l+r)>>1; if(L<=mid)change(ls,l,mid,L,R,f); if(R>mid)change(rs,mid+1,r,L,R,f); upd(x,l,r); //int find(int x,int l,int r) // while(l<=r) // int mid=l+r>>1; // if(hsh[mid]<x)l=mid+1; // else if(hsh[mid]==x)return mid; // else r=mid-1; // // int solve() int res=0; sort(hsh+1,hsh+1+cnt); sort(e+1,e+1+cnt); for(int i=1;i<=cnt;i++) int l=lower_bound(hsh+1,hsh+1+cnt,e[i].l)-hsh, r=lower_bound(hsh+1,hsh+1+cnt,e[i].r)-hsh-1;//这里要减一线段树维护的长度才正确 // int l=find(e[i].l,1,cnt),r=find(e[i].r,1,cnt)-1; if(l<=r) int lst=t[1].sum; change(1,1,cnt,l,r,e[i].f); res+=abs(t[1].sum-lst); return res; int main() scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d%d",&r[i].xa,&r[i].ya,&r[i].xb,&r[i].yb); hsh[++cnt]=r[i].xa;e[cnt].l=r[i].xa; e[cnt].r=r[i].xb;e[cnt].h=r[i].ya;e[cnt].f=1; hsh[++cnt]=r[i].xb;e[cnt].l=r[i].xa; e[cnt].r=r[i].xb,e[cnt].h=r[i].yb,e[cnt].f=-1; ans+=solve(); cnt=0; for(int i=1;i<=n;i++) hsh[++cnt]=r[i].ya,e[cnt].l=r[i].ya; e[cnt].r=r[i].yb,e[cnt].h=r[i].xa,e[cnt].f=1; hsh[++cnt]=r[i].yb,e[cnt].l=r[i].ya; e[cnt].r=r[i].yb,e[cnt].h=r[i].xb,e[cnt].f=-1; ans+=solve(); printf("%d",ans);
POJ_1151_Atlantis
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ls (x<<1) #define rs (x<<1|1) #define ll long long using namespace std; const int maxn=509; int n; double ans; struct node double xa,xb,ya,yb; r[maxn]; double hsh[maxn<<1];int cnt; struct line double l,r,h; int f; bool operator <(const line &a)const return h<a.h || h==a.h && f>a.f; e[maxn<<1]; struct tree double sum; int tag; t[maxn<<2]; void upd(int x,int l,int r) if(t[x].tag)t[x].sum=hsh[r+1]-hsh[l]; else if(l==r)t[x].sum=0; else t[x].sum=t[ls].sum+t[rs].sum; void change(int x,int l,int r,int L,int R,int f) if(L<=l && r<=R) t[x].tag+=f; else int mid=l+r>>1; if(L<=mid)change(ls,l,mid,L,R,f); if(R>mid)change(rs,mid+1,r,L,R,f); upd(x,l,r); double solve() double res=0; sort(hsh+1,hsh+1+cnt); sort(e+1,e+1+cnt); int tot=unique(hsh+1,hsh+1+cnt)-hsh-1; for(int i=1;i<cnt;i++) int l=lower_bound(hsh+1,hsh+1+tot,e[i].l)-hsh, r=lower_bound(hsh+1,hsh+1+tot,e[i].r)-hsh-1; if(l<=r) change(1,1,tot,l,r,e[i].f); res+=fabs(t[1].sum)*(e[i+1].h-e[i].h); return res; int main()int tt=0; while(scanf("%d",&n) && n)tt++; cnt=0; memset(hsh,0,sizeof(hsh)); memset(t,0,sizeof(t)); for(int i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&r[i].xa,&r[i].ya,&r[i].xb,&r[i].yb); hsh[++cnt]=r[i].xa; e[cnt].l=r[i].xa; e[cnt].r=r[i].xb; e[cnt].h=r[i].ya; e[cnt].f=1; hsh[++cnt]=r[i].xb; e[cnt].l=r[i].xa; e[cnt].r=r[i].xb; e[cnt].h=r[i].yb; e[cnt].f=-1; printf("Test case #%d\n",tt); printf("Total explored area: %.2f\n\n",solve());
以上是关于[题解/模板]扫描线的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 5770 Treasure 思维 + 扫描线 + 线段树 (看题解)
Gym 100733J Summer Wars 题解:灵活运用扫描线的思想