hdu1828 Picture (线段树:扫描线周长)
Posted guapisolo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu1828 Picture (线段树:扫描线周长)相关的知识,希望对你有一定的参考价值。
依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长。
容易发现,扫描线中的某一条横边对答案的贡献。
其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值
然后横着竖着都做一遍就行了
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 10010 5 #define ll long long 6 using namespace std; 7 8 int n,sz; 9 int a[N],cnt[N<<2],sum[N<<2]; 10 struct SQU{ 11 int a1,b1,a2,b2; 12 }q[N]; 13 struct node{ 14 int l,r,la,ra,h,f; 15 }sc[N]; 16 int cmp1(node s1,node s2){ 17 if(s1.h!=s2.h) return s1.h<s2.h; 18 else return s1.f>s2.f; 19 } 20 void pushup(int l,int r,int rt) 21 { 22 if(cnt[rt]>0) sum[rt]=a[r+1]-a[l]; 23 else if(l==r) sum[rt]=0; 24 else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 25 } 26 void update(int L,int R,int l,int r,int rt,int w) 27 { 28 if(L<=l&&r<=R) 29 { 30 cnt[rt]+=w; 31 pushup(l,r,rt); 32 return; 33 } 34 int mid=(l+r)>>1; 35 if(L<=mid) update(L,R,l,mid,rt<<1,w); 36 if(R>mid) update(L,R,mid+1,r,rt<<1|1,w); 37 pushup(l,r,rt); 38 } 39 void clr() 40 { 41 memset(a,0,sizeof(a)); 42 memset(sc,0,sizeof(sc)); 43 memset(cnt,0,sizeof(cnt)); 44 memset(sum,0,sizeof(sum)); 45 } 46 int solvex() 47 { 48 int ans=0,lst=0; 49 for(int i=1;i<=n;i++) 50 { 51 a[2*i-1]=q[i].a1,a[2*i]=q[i].a2; 52 sc[2*i-1].l=q[i].a1,sc[2*i].l=q[i].a1; 53 sc[2*i-1].r=q[i].a2,sc[2*i].r=q[i].a2; 54 sc[2*i-1].h=q[i].b1,sc[2*i].h=q[i].b2; 55 sc[2*i-1].f=1,sc[2*i].f=-1; 56 } 57 sort(a+1,a+2*n+1); 58 sz=unique(a+1,a+2*n+1)-(a+1); 59 sort(sc+1,sc+2*n+1,cmp1); 60 for(int i=1;i<=2*n;i++) 61 { 62 int la=lower_bound(a+1,a+sz+1,sc[i].l)-a; 63 int ra=lower_bound(a+1,a+sz+1,sc[i].r)-a; 64 lst=sum[1]; 65 update(la,ra-1,1,sz,1,sc[i].f); 66 ans+=abs(sum[1]-lst); 67 } 68 return ans; 69 } 70 int solvey() 71 { 72 int ans=0,lst=0; 73 for(int i=1;i<=n;i++) 74 { 75 a[2*i-1]=q[i].b1,a[2*i]=q[i].b2; 76 sc[2*i-1].l=q[i].b1,sc[2*i].l=q[i].b1; 77 sc[2*i-1].r=q[i].b2,sc[2*i].r=q[i].b2; 78 sc[2*i-1].h=q[i].a1,sc[2*i].h=q[i].a2; 79 sc[2*i-1].f=1,sc[2*i].f=-1; 80 } 81 sort(a+1,a+2*n+1); 82 sz=unique(a+1,a+2*n+1)-(a+1); 83 sort(sc+1,sc+2*n+1,cmp1); 84 for(int i=1;i<=2*n;i++) 85 { 86 int la=lower_bound(a+1,a+sz+1,sc[i].l)-a; 87 int ra=lower_bound(a+1,a+sz+1,sc[i].r)-a; 88 lst=sum[1]; 89 update(la,ra-1,1,sz,1,sc[i].f); 90 ans+=abs(sum[1]-lst); 91 } 92 return ans; 93 } 94 95 int main() 96 { 97 //freopen("data.in","r",stdin); 98 scanf("%d",&n); 99 for(int i=1;i<=n;i++) 100 scanf("%d%d%d%d",&q[i].a1,&q[i].b1,&q[i].a2,&q[i].b2); 101 int ret=0; 102 ret+=solvex(); 103 clr(); 104 ret+=solvey(); 105 printf("%d ",ret); 106 return 0; 107 }
以上是关于hdu1828 Picture (线段树:扫描线周长)的主要内容,如果未能解决你的问题,请参考以下文章
51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)