标签:ios upd int string test 长度 def ring can
经典题,线段树扫描线其实类似区间更新,一般的做法是想象一根扫描线从上扫到下或者从左扫到右,本题的做法是从上扫到下
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define maxn 2000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; struct Seg{ double l,r,h; int d; Seg(){} Seg(double a,double b,double c,int dd):l(a),r(b),h(c),d(dd){} bool operator<(const Seg & a)const{ return h<a.h; }//从下往上扫描 }segs[maxn];//横线段 double data[maxn]; int tot,m;//data统计高度 int cnt[maxn<<2];//覆盖了这一整个区间的入边数 - 覆盖了这一整个区间的出边数 double sum[maxn<<2];//区间当前被覆盖的长度 inline void pushup(int l,int r,int rt){ //前两个if对应的是update中(L<=l && R>=r)的pushup,后一个if对应的是分开更新后的update if(cnt[rt])//如果这个区间都被覆盖了 sum[rt]=data[r+1]-data[l]; else if (l==r)//如果是单位段并且cnt[rt]==0,说明这一段就是没有被覆盖 sum[rt]=0; else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } //更新函数update:如果整个区间被更新,分三种情况:1.这个区间被完全覆盖 2.这个区间是空白单位区间(没有子区间) 3.这个区间没有被完全覆盖 void update(int L,int R,int c,int l,int r,int rt){ if(L<=l && R>=r){ cnt[rt]+=c; pushup(l,r,rt);//为什么这里也会有pushup?因为pushup的功能不只是合并两个区间而已,它还能计算这个区间的覆盖长度 return; } int m=l+r>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); pushup(l,r,rt); } void init(){ tot=m=0; memset(cnt,0,sizeof cnt); memset(sum,0,sizeof sum); } int main(){ int T=0,n; while(scanf("%d",&n) && n){ init(); for(int i=1;i<=n;i++){ double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); segs[tot]=Seg(x1,x2,y1,1);data[tot++]=x1; segs[tot]=Seg(x1,x2,y2,-1);data[tot++]=x2; } sort(segs,segs+tot); sort(data,data+tot); m=unique(data,data+tot)-data; double ret=0; for(int i=0;i<tot;i++){ int posl=lower_bound(data,data+m,segs[i].l)-data; int posr=lower_bound(data,data+m,segs[i].r)-data-1; if(posl<=posr) update(posl,posr,segs[i].d,0,m,1);//把这条边更新到线段树中 ret+=sum[1]*(segs[i+1].h-segs[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n",++T , ret); } return 0; }
标签:ios upd int string test 长度 def ring can
原文地址:https://www.cnblogs.com/zsben991126/p/9941032.html