1. 程式人生 > >Codeforces 610D Vika and Segments

Codeforces 610D Vika and Segments

pre span fin mes gif 想想 img color pda

題目大意:給你n(n<=1e9)條垂直於x軸或者與x軸平行的線,問你這些線占了多少個點。

寫的時候感覺就是一道線段樹,可是想不出來,後來題解說可以轉化成面積問題,就知道

怎麽寫了,是一道線段樹加掃描線求面積並的問題。

思路:將一條線轉化為寬度為1的矩形,然後用線段樹+掃描線+離散化求面積並就行了,

順便幫我復習了一下掃描線。。 以後要多想想怎麽轉化不能這麽菜了!!!!

技術分享
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
using
namespace std; const int N=2*1e5+3; struct line { int x,y1,y2,op; bool operator < (const line &t)const { if(x==t.x) return op<t.op; return x<t.x; } }e[N]; int n,y[N],tot=0,cnt=0; int seg[N<<2],cover[N<<2]; //seg[i] 表示i這個區域內的覆蓋長度,cover表示覆蓋了幾次。 void
push_up(int rt,int l,int r,int op) { if(cover[rt]>=1) seg[rt]=y[r+1]-y[l]; else if(l==r) { if(op==1) seg[rt]=y[r+1]-y[l]; else seg[rt]=0; } else seg[rt]=seg[rt<<1]+seg[rt<<1|1]; } void updata(int L,int R,int l,int r,int rt,int g) { if(l>=L && r<=R) { cover[rt]
+=g; push_up(rt,l,r,g); return; } int m=(l+r)>>1; if(L<=m) updata(L,R,lson,g); if(R>m) updata(L,R,rson,g); push_up(rt,l,r,g); } int main() { cin>>n; for(int i=1;i<=n;i++) { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(y1>y2) swap(y1,y2),swap(x1,x2); if(y1==y2) { e[tot].x=x1; e[tot].y1=y1; e[tot++].y2=y1+1; e[tot].x=x2; e[tot].y1=y1; e[tot++].y2=y1+1; y[cnt++]=y1; y[cnt++]=y1+1; if(x1>x2) e[tot-2].x+=1,e[tot-1].op=1,e[tot-2].op=-1; else e[tot-1].x+=1,e[tot-2].op=1,e[tot-1].op=-1; } else { e[tot].x=x1; e[tot].op=1; e[tot].y1=y1; e[tot++].y2=y2+1; e[tot].x=x1+1; e[tot].op=-1; e[tot].y1=y1; e[tot++].y2=y2+1; y[cnt++]=y1; y[cnt++]=y2+1; if(x1>x2) e[tot-1].op=1,e[tot-2].op=-1; else e[tot-1].op=-1,e[tot-2].op=1; } } sort(y,y+cnt); sort(e,e+tot); cnt=unique(y,y+cnt)-y; ll ans=0,pre=-1e18; for(int i=0;i<tot;i++) { if(pre!=-1e18) ans+=(ll)(e[i].x-pre)*(ll)seg[1]; int up=lower_bound(y,y+cnt,e[i].y2)-y; int down=lower_bound(y,y+cnt,e[i].y1)-y; updata(down,up-1,0,tot-1,1,e[i].op); pre=e[i].x; } cout<<ans<<endl; return 0; }
View Code

Codeforces 610D Vika and Segments