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 }

 

posted @ 2014-10-02 22:36  Naturain  阅读(185)  评论(0)    收藏  举报