| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
扫面线简便做法RT
看了很多题解都是横边和竖边同时统计,要维护的值较多。
其实求竖边或横边之一只用维护当前扫描的总长度,计算与上次的差值。
算完之后在将图形整体旋转90度,再算一遍即可。
甚至可以直接把求面积并的代码改一改就过了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e4+5;
int n,l1[MAXN],l2[MAXN],r1[MAXN],r2[MAXN],tr[MAXN<<2],b[MAXN<<2],wz[MAXN<<1],M,ans;
struct node
{
int L,R,h,num;
bool operator<(const node &o) const
{
return h<o.h;
}
}a[MAXN<<1];
void add(int u,int l,int r,int L,int R,int x)
{
// cout<<u<<" "<<l<<' '<<r<<' '<<wz[l]<<' '<<wz[r+1]<<' '<<L<<' '<<R<<endl;
if(L>=wz[r+1]||wz[l]>=R) return;
if(L<=wz[l]&&wz[r+1]<=R)
{
b[u]+=x;
if(b[u]>0) tr[u]=wz[r+1]-wz[l];
else tr[u]=tr[u*2]+tr[u*2+1];//cout<<u<<" "<<l<<" "<<r<<' '<<b[u]<<' '<<tr[u]<<endl;
return;
}
int mid=(l+r)/2;
add(u*2,l,mid,L,R,x),add(u*2+1,mid+1,r,L,R,x);
if(b[u]>0) tr[u]=wz[r+1]-wz[l];
else tr[u]=tr[u*2]+tr[u*2+1];
// cout<<u<<" "<<l<<" "<<r<<' '<<b[u]<<' '<<tr[u]<<endl;
}
void solve()
{
memset(tr,0,sizeof(tr));
memset(b,0,sizeof(b));
M=0;
for(int i=1;i<=n;i++)
{
a[++M]=(node){l1[i],r1[i],l2[i],1},a[++M]=(node){l1[i],r1[i],r2[i],-1};
wz[M-1]=l1[i],wz[M]=r1[i];
}
sort(a+1,a+M+1);
sort(wz+1,wz+M+1);
int lst=0;
for(int i=1;i<=M;i++)
{
add(1,1,M-1,a[i].L,a[i].R,a[i].num);
// cout<<i<<' '<<ans<<endl;
ans+=abs(tr[1]-lst),lst=tr[1];
}
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld%lld%lld%lld",&l1[i],&l2[i],&r1[i],&r2[i]);
solve();
for(int i=1;i<=n;i++) swap(l1[i],l2[i]),swap(r1[i],r2[i]);
solve();
cout<<ans;
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator