題意 一開始想到用二維線段樹,但是我沒寫過二維的,只寫過一維的。后來問了下別人,說一維也行(一開始我也想到是不是可以用一維的,但是很快就被我自己給否定了,我認為那樣時間會不夠的,后來再第11個點還真的不夠)。于是就寫了一個一維的線段樹。把每一行進行一次線段樹操作。這樣空間也可以開出來,變成復雜度也不高。可是交上去之后在第11個點超時了。給的是2S,我的運行了2.67S。有人說可以從后往前染色,那樣的話,如果某個區域已經染色了,那么后面就不用在染色了,因為在染色是沒有意義的。無奈不會實現,想著用并查集稍微加速下,可是發現不怎么好合并(哪位高人看了給指點指點,看到一牛人寫了點,不過由于水平問題,實在不知并查集怎么實現這個問題的),于是一直TLE,今天看了nocow的題解,發現基本是用矩形切割做的.推薦看薛茅的論文,開始對這個東西我還一無所知。終于在那看到個線段樹的,第11組數據也只有0.7S。后來看了下,發現那個程序也是用一維的線段樹搞的,不過比我的實現的好,首先不是每一行都進行一次線段樹操作,那樣時間肯定是不夠的。我們來看下面這幅圖, 圖中的黑色框是原矩形,紅色的是我們投影的那些值(這里沒有畫大矩形的兩條邊)。 我們首先對垂直X軸的邊投影(其中包括原來大矩形的兩條邊),得到一些列的值,那么以后只要對這些值中相鄰的兩個之間(圖中的紅色線條之間的區域)進行一次線段樹的操作這樣的話可以減少不少的操作,也就是說原來的一行進行一次,可以把某些行進行合并,因為這些行(每兩條相鄰的紅色線段之間的行)的顏色都一樣的。這樣操作之后最大一組數據用時0.7S. 似乎這題的標準解法是矩形切割。到時再去看看。
下面再看看矩形切割的方法。(代碼不是我的。官方的,我只加了點注釋) 直接上代碼 下面的一個圖貼在代碼里面會亂,在這貼下吧(我無語了,還是會亂,只好截圖了)

 CODE 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 FILE *fp,*fo;/**//*輸入輸出文件*/ 6 7 struct rect 8  {/**//*矩形結構體*/ 9 int c; 10 int x1,y1,x2,y2; 11 }; 12 13 int c[2501];/**//*顏色的多少*/ 14 rect r[10001]; 15 16 int intersect(rect a,const rect &b,rect out[4]) 17  { 18 /**//* do they at all intersect? */ 19 if(b.x2<a.x1||b.x1>=a.x2) 20 return 0; 21 if(b.y2<a.y1||b.y1>=a.y2) 22 return 0; 23 /**//*上面表示不相交*/ 24 /**//* they do */ 25 26 rect t; 27 28 if(b.x1<=a.x1&&b.x2>=a.x2&&b.y1<=a.y1&&b.y2>=a.y2) 29 return -1; /**//*全部覆蓋前面的某個矩形*/ 30 31 /**//* cutting `a' down to match b */ 32 /**//*********************** 33 +--------+ +-+--+--+ 34 | | | |2 | | 35 | | + +--+ | 36 | +-+ | --> | | | | 37 | +-+ | |1 | |3 | 38 | | | +--+ | 39 | | | | 4 | | 40 +--------+ +-+--+--+ 41 ***********************/ 42 int nout=0;/**//*記錄分成多少塊*/ 43 if(b.x1>=a.x1) {/**//*上右圖中的1*/ 44 t=a,t.x2=b.x1; 45 if(t.x1!=t.x2) 46 out[nout++]=t; 47 a.x1=b.x1; 48 } 49 if(b.x2<a.x2) {/**//*上右圖中的3*/ 50 t=a,t.x1=b.x2; 51 if(t.x1!=t.x2) 52 out[nout++]=t; 53 a.x2=b.x2; 54 } 55 if(b.y1>=a.y1) {/**//*上右圖中的4*/ 56 t=a,t.y2=b.y1; 57 if(t.y1!=t.y2) 58 out[nout++]=t; 59 a.y1=b.y1; 60 } 61 if(b.y2<a.y2) {/**//*上右圖中的2*/ 62 t=a,t.y1=b.y2; 63 if(t.y1!=t.y2) 64 out[nout++]=t; 65 a.y2=b.y2; 66 } 67 return nout; 68 } 69 70 int main(void) { 71 fp=fopen("rect1.in","rt"); 72 fo=fopen("rect1.out","wt"); 73 74 int a,b,n; 75 fscanf(fp,"%d %d %d",&a,&b,&n); 76 /**//*把原始矩形加進去*/ 77 r[0].c=1; 78 r[0].x1=r[0].y1=0; 79 r[0].x2=a; 80 r[0].y2=b; 81 82 rect t[4]; 83 84 int i,j,rr=1; 85 for(i=0;i<n;i++) 86 { 87 int tmp; 88 fscanf(fp,"%d %d %d %d %d",&r[rr].x1,&r[rr].y1,&r[rr].x2,&r[rr].y2,&r[rr].c); 89 90 if(r[rr].x1>r[rr].x2) 91 { 92 tmp=r[rr].x1; 93 r[rr].x1=r[rr].x2; 94 r[rr].x2=tmp; 95 } 96 if(r[rr].y1>r[rr].y2) 97 { 98 tmp=r[rr].y1; 99 r[rr].y1=r[rr].y2; 100 r[rr].y2=tmp; 101 } 102 103 int nr=rr; 104 rect curr=r[rr++]; 105 for(j=0;j<nr;j++) 106 { 107 int n=intersect(r[j],curr,t); 108 if(!n)/**//*和r[j]不相交*/ 109 continue; 110 if(n==-1) 111 {/**//*全部覆蓋r[j]*/ 112 memmove(r+j,r+j+1,sizeof(rect)*(rr-j-1)); 113 /**//*把r數組從r[j+1]全部往前移一位*/ 114 j--;/**//*進行相應的調整*/ 115 rr--; 116 nr--; 117 continue; 118 } 119 r[j]=t[--n];/**//*分成幾塊*/ 120 for(;n-->0;)/**//*把分成的幾塊加進去*/ 121 r[rr++]=t[n]; 122 } 123 } 124 125 for(i=0;i<rr;i++)/**//*現在每一塊都是單一顏色的 直接統計*/ 126 c[r[i].c]+=(r[i].x2-r[i].x1)*(r[i].y2-r[i].y1); 127 128 for(i=1;i<=2500;i++) 129 if(c[i])/**//*輸出*/ 130 fprintf(fo,"%d %d\n",i,c[i]); 131 132 return 0; 133 } 134
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
常用鏈接
留言簿(1)
隨筆分類(99)
隨筆檔案(71)
好友鏈接
搜索
最新評論

閱讀排行榜
評論排行榜
|
|