HDU1255 覆盖的面积(线段树+扫描线)
对于覆盖的一次的,我们维护一格变量,对于覆盖两次的,我们维护两个变量,分别是s1,s2,覆盖一次以上和覆盖两次以上。
通过这样的操作就可以直接根据儿子信息更新而不用维护一格pushdown操作
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int N=3e5+10; const int mod=1e9+7; struct node{ int l,r,lazy; double s1,s2; }tr[N]; vector<double> num; struct qi{ double x; double y,y2; int k; bool operator <(const qi& t) const{ return x<t.x; } }sg[N]; int find(double x){ return lower_bound(num.begin(),num.end(),x)-num.begin()+1; } void build(int u,int l,int r){ if(l==r){ tr[u]=node{l,l,0,0,0}; } else{ tr[u]=node{l,r,0,0,0}; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } } void pushup(int u){ if(tr[u].lazy>=2){ tr[u].s2=num[tr[u].r]-num[tr[u].l-1]; tr[u].s1 =num[tr[u].r]-num[tr[u].l-1]; } else if(tr[u].lazy==1){ tr[u].s2=tr[u<<1].s1+tr[u<<1|1].s1; tr[u].s1 =num[tr[u].r]-num[tr[u].l-1]; } else{ if(tr[u].l==tr[u].r) tr[u].s2 = tr[u].s1 = 0; else{ tr[u].s2= tr[u<<1].s2+tr[u<<1|1].s2; tr[u].s1 = tr[u<<1].s1+tr[u<<1|1].s1; } } } void modify(int u,int l,int r,int x){ if(tr[u].l>=l&&tr[u].r<=r){ tr[u].lazy+=x; pushup(u); return ; } int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,x); if(r>mid) modify(u<<1|1,l,r,x); pushup(u); } int main(){ int n; int t; cin>>t; while(t--){ cin>>n; num.clear(); int i; double x1,x2,y,y2; int cnt=1; for(i=1;i<=n;i++){ scanf("%lf%lf%lf%lf",&x1,&y,&x2,&y2); sg[cnt++]={x1,y,y2,1}; sg[cnt++]={x2,y,y2,-1}; num.push_back(y); num.push_back(y2); } sort(sg+1,sg+1+2*n); sort(num.begin(),num.end()); num.erase(unique(num.begin(),num.end()),num.end()); build(1,1,num.size()-1); double sum=0; for(i=1;i<=2*n;i++){ if(i>1){ sum+=tr[1].s2*(sg[i].x-sg[i-1].x); } modify(1,find(sg[i].y),find(sg[i].y2)-1,sg[i].k); } printf("%.2f\n",sum); } return 0; }
没有人不辛苦,只有人不喊疼