Poj--3695(线段树,扫描线,离散化)
2014-10-02 22:30:57
思路:这题让我熟悉了扫描线的思想。为什么扫描线的Update是精确更新?(即:查询区间刚好等于当前区间)因为这种扫描线写法没有query,所以不能用lazy的思想。
好了,上面都是题外话。考虑到这题的矩形个数很小 <= 20,但查询很多,所以可以根据每个查询进行一次扫描线,但要注意不是每查询一次就重建一棵树。因为扫描线后线段树自然地回到扫描前,所以不用重建。要考虑的几个细节:(1)离散化(即使点的坐标<=1000,但离散化后<=40,log1000 和 log40 效率还是有差的)(2)可以通过预处理而防止每次查询都对边进行排序。
1 /************************************************************************* 2 > File Name: 3695.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Thu 02 Oct 2014 01:14:01 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 #define lp (p << 1) 18 #define rp (p << 1|1) 19 #define getmid(l,r) (l + (r - l) / 2) 20 typedef long long ll; 21 const int INF = 1 << 30; 22 const int maxn = 25; 23 24 int N,M; 25 int x[maxn << 1]; 26 27 struct Rec{ 28 int x1,y1,x2,y2; 29 }rec[maxn]; 30 31 struct Seg{ 32 int x1,x2,y; 33 int flag; 34 int id; 35 friend bool operator < (Seg a,Seg b){ return a.y < b.y;} 36 }s[maxn << 1]; 37 38 struct node{ 39 int l,r; 40 int tl,tr,len; 41 int cover; 42 }t[maxn << 3]; 43 44 void Build_tree(int p,int l,int r){ 45 t[p].l = l; 46 t[p].r = r; 47 t[p].tl = x[l]; 48 t[p].tr = x[r]; 49 t[p].len = t[p].cover = 0; 50 if(l + 1 == r) 51 return; 52 int mid = getmid(l,r); 53 Build_tree(lp,l,mid); 54 Build_tree(rp,mid,r); 55 } 56 57 void Cal_len(int p){ 58 if(t[p].cover > 0) 59 t[p].len = t[p].tr - t[p].tl; 60 else if(t[p].l + 1 == t[p].r) 61 t[p].len = 0; 62 else 63 t[p].len = t[lp].len + t[rp].len; 64 } 65 66 void Update_tree(int a,int b,int c,int p,int l,int r){ 67 if(a == t[p].tl && t[p].tr == b){ 68 t[p].cover += c; 69 Cal_len(p); 70 return; 71 } 72 int mid = getmid(l,r); 73 if(a >= t[rp].tl) Update_tree(a,b,c,rp,mid,r); 74 else if(b <= t[lp].tr) Update_tree(a,b,c,lp,l,mid); 75 else{ 76 Update_tree(a,t[lp].tr,c,lp,l,mid); 77 Update_tree(t[rp].tl,b,c,rp,mid,r); 78 } 79 Cal_len(p); 80 } 81 82 int main(){ 83 int k,v; 84 int Case = 0; 85 while(scanf("%d%d",&N,&M) != EOF){ 86 if(N == 0 && M == 0) 87 break; 88 int cnt = 0; 89 for(int i = 1; i <= N; ++i){ 90 scanf("%d%d%d%d",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2); 91 s[++cnt].x1 = rec[i].x1; 92 s[cnt].x2 = rec[i].x2; 93 s[cnt].y = rec[i].y1; 94 s[cnt].flag = 1; 95 s[cnt].id = i; 96 x[cnt] = rec[i].x1; 97 98 s[++cnt].x1 = rec[i].x1; 99 s[cnt].x2 = rec[i].x2; 100 s[cnt].y = rec[i].y2; 101 s[cnt].flag = -1; 102 s[cnt].id = i; 103 x[cnt] = rec[i].x2; 104 } 105 sort(x + 1,x + cnt + 1); 106 sort(s + 1,s + cnt + 1); 107 Build_tree(1,1,cnt); 108 printf("Case %d:\n",++Case); 109 int ans,v,pre,vis[maxn << 1]; 110 for(int i = 1; i <= M; ++i){ 111 scanf("%d",&k); 112 memset(vis,0,sizeof(vis)); 113 for(int j = 1; j <= k; ++j){ 114 scanf("%d",&v); 115 vis[v] = 1; 116 } 117 ans = 0; 118 pre = 0; 119 for(int j = 1; j <= cnt; ++j) if(vis[s[j].id]){ 120 if(pre) ans += t[1].len * (s[j].y - s[pre].y); 121 Update_tree(s[j].x1,s[j].x2,s[j].flag,1,1,cnt); 122 pre = j; 123 } 124 printf("Query %d: %d\n",i,ans); 125 } 126 puts(""); 127 } 128 return 0; 129 }

浙公网安备 33010602011771号