问题来源:IOI1998 D2T1
题意:就是在一个平面内给出n个矩形,叫你计算将这些矩形合并以后,新图形的周长。
例如:
上图是原本的矩形们 ---------->合并后的图形
解题思路:拿一条扫描线横着扫一次,遇到左边的边就在这条扫描线上+1,遇到右边的边就在这条扫描线上-1,在边被扫到的时候计算一下线上为0的个数即可。
因为如果只是单纯的For循环累加,时间会爆,所以我们采用线段树来存这条扫描线的状态优化效率即可。然后竖着再做同样的事做一遍。
时间效率应该是O(kn)(k是常数)。
附代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 #define For(i,a,b) for (int i=a; i<=b; i++) 8 #define Ford(i,a,b) for (int i=a; i>=b; i--) 9 #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); 10 #define mem(qaq,num) memset(qaq,num,sizeof(qaq)); 11 #define ll long long 12 #define mod 1000000007 13 #define INF 2000000000 14 #define mid ((l+r)>>1) 15 using namespace std; 16 struct zxy{ 17 int mi,n,mark; 18 }tr[65540]; 19 struct edge{ 20 int l,r,h,typ; 21 }x[10001],y[10001]; 22 int n,ans,cnt; 23 inline int in(){ 24 int x=0,f=1; 25 char ch=getchar(); 26 while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar(); 27 while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 28 return x*f; 29 } 30 inline void combine(int k){ 31 if (tr[k<<1].mi==tr[k<<1|1].mi) tr[k].n=tr[k<<1].n+tr[k<<1|1].n,tr[k].mi=tr[k<<1].mi; 32 else 33 if(tr[k<<1].mi<tr[k<<1|1].mi) tr[k].n=tr[k<<1].n,tr[k].mi=tr[k<<1].mi; 34 else tr[k].n=tr[k<<1|1].n,tr[k].mi=tr[k<<1|1].mi; 35 return; 36 } 37 inline void built(int l,int r,int k){ 38 if (l==r){ 39 tr[k].mi=0; 40 tr[k].n=1; 41 tr[k].mark=0; 42 return; 43 } 44 built(l,mid,k<<1); 45 built(mid+1,r,k<<1|1); 46 combine(k); 47 tr[k].mark=0; 48 } 49 inline void pushdown(int k){ 50 int ad=tr[k].mark; 51 tr[k<<1].mark+=ad; 52 tr[k<<1|1].mark+=ad; 53 tr[k<<1].mi+=ad; 54 tr[k<<1|1].mi+=ad; 55 tr[k].mark=0; 56 return; 57 } 58 inline void update(int l,int r,int a,int b,int k,int ad){ 59 if (l>=a&&b>=r){ 60 tr[k].mark+=ad; 61 tr[k].mi+=ad; 62 return; 63 } 64 if (tr[k].mark) pushdown(k); 65 if (a<=mid) update(l,mid,a,b,k<<1,ad); 66 if (b>mid) update(mid+1,r,a,b,k<<1|1,ad); 67 combine(k); 68 return; 69 } 70 inline int query(int l,int r,int k,int a,int b){ 71 if (l==a&&r==b){ 72 if (tr[k].mi) return 0; 73 return tr[k].n; 74 } 75 if (tr[k].mark) pushdown(k); 76 if (b<=mid) return query(l,mid,k<<1,a,b); 77 if (a>mid) return query(mid+1,r,k<<1|1,a,b); 78 return query(l,mid,k<<1,a,mid)+query(mid+1,r,k<<1|1,mid+1,b); 79 } 80 void init(){ 81 n=in(); 82 For(i,1,n){ 83 int x1=in()+10001,y1=in()+10001,x2=in()+10001,y2=in()+10001; 84 x[++cnt].l=x1+1,x[cnt].r=x2,x[cnt].h=y1,x[cnt].typ=0; 85 y[cnt].l=y1+1,y[cnt].r=y2,y[cnt].h=x1,y[cnt].typ=0; 86 x[++cnt].l=x1+1,x[cnt].r=x2,x[cnt].h=y2,x[cnt].typ=1; 87 y[cnt].l=y1+1,y[cnt].r=y2,y[cnt].h=x2,y[cnt].typ=1; 88 } 89 return; 90 } 91 bool cmp(edge a,edge b){ 92 return a.h<b.h||(a.h==b.h&&a.typ<b.typ); 93 } 94 void work(){ 95 sort(x+1,x+cnt+1,cmp); 96 built(1,20001,1); 97 For(i,1,cnt) 98 if (!x[i].typ){ 99 ans+=query(1,20001,1,x[i].l,x[i].r); 100 update(1,20001,x[i].l,x[i].r,1,1); 101 } 102 else{ 103 update(1,20001,x[i].l,x[i].r,1,-1); 104 ans+=query(1,20001,1,x[i].l,x[i].r); 105 } 106 sort(y+1,y+cnt+1,cmp); 107 built(1,20001,1); 108 For(i,1,cnt) 109 if (!y[i].typ){ 110 ans+=query(1,20001,1,y[i].l,y[i].r); 111 update(1,20001,y[i].l,y[i].r,1,1); 112 } 113 else{ 114 update(1,20001,y[i].l,y[i].r,1,-1); 115 ans+=query(1,20001,1,y[i].l,y[i].r); 116 } 117 return; 118 } 119 int main(){ 120 init(); 121 work(); 122 printf("%d",ans); 123 }
本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.