CodeChef - QRECT Rectangle Query CDQ分治

题目传送门

题解:现在需要维护的每次的询问矩形和前面插入的所有矩形有公共部分的个数。 我们试着直接去维护这个东西, 发现可能的情况太多,不好维护,所以我们维护每次询问的时候在当前矩阵个数下,有多少个矩阵是一定在外面的。对于一个矩阵来说, 我们只需要统计到目前位置, 多少个矩形的下底线 在询问矩形的上底线之上, 这样我们就减去了在询问矩形上方的不重合矩形。 然后我们对矩形的左右下也一样维护这个信息。对于这个操作我们可以用4个树状数组直接去维护这个信息。每个数状数组记录一下每条底线出现的位置。

维护完这个东西之后,我们发现如果一个矩形在询问矩形的左上方, 他会被减去2次,这样就多减了, 我们需要把左上角的矩形个数再加回去。 我们需要 对每个询问矩形来说, 维护出有多少个插入矩形的右下角的端点是在询问矩形的左上角的端点的左上角, 对于这个问题就变成了一个2维偏序问题,我们用cdq去维护这个信息。当然还有其他3个角落,我们也需要对那些角度做一样的操作。最后我们就可以得到答案了。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define lch(x) tr[x].son[0]
 12 #define rch(x) tr[x].son[1]
 13 #define max3(a,b,c) max(a,max(b,c))
 14 #define min3(a,b,c) min(a,min(b,c))
 15 typedef pair<int,int> pll;
 16 const int inf = 0x3f3f3f3f;
 17 const LL INF = 0x3f3f3f3f3f3f3f3f;
 18 const LL mod =  (int)1e9+7;
 19 const int N = 2e5 + 100;
 20 struct Node{
 21     int x1, y1, x2, y2, op, id;
 22 }A[N], B[N];
 23 int xsz, ysz;
 24 int x[N], y[N];
 25 int tmp[N];
 26 int ans[N];
 27 char s[10];
 28 struct bit_tree{
 29     int tree[N], tot;
 30     void add(int x, int v){
 31         for(int i = x; i < N; i += i & (-i)){
 32             tree[i] += v;
 33         }
 34         tot += v;
 35     }
 36     int query(int x){
 37         int ret = 0;
 38         for(int i = x; i > 0; i -= i & (-i)){
 39             ret += tree[i];
 40         }
 41         return ret;
 42     }
 43     void Clear(){
 44         tot = 0;
 45         memset(tree, 0, sizeof(tree));
 46     }
 47 }bit[4];
 48 bool cmp1(Node & a, Node & b){
 49     int aop = abs(a.op), bop = abs(b.op);
 50     int ax, bx;
 51     if(aop) ax = a.x2;
 52     else ax = a.x1;
 53     if(bop) bx = b.x2;
 54     else bx = b.x1;
 55     if(ax != bx) return ax < bx;
 56     return aop < bop;
 57 }
 58 bool cmp2(Node & a, Node & b){
 59     int aop = abs(a.op), bop = abs(b.op);
 60     int ax, bx;
 61     if(!aop) ax = a.x2;
 62     else ax = a.x1;
 63     if(!bop) bx = b.x2;
 64     else bx = b.x1;
 65     if(ax != bx) return ax > bx;
 66     return aop < bop;
 67 }
 68 void cdq(int l, int r){
 69     if(l >= r) return ;
 70     int mid = l+r >> 1;
 71     cdq(l, mid);
 72     cdq(mid+1, r);
 73     int top = 0;
 74     for(int i = l; i <= mid; i++)
 75         if(A[i].op)  B[++top] = A[i];
 76     for(int i = mid+1; i <= r; i++)
 77         if(!A[i].op) B[++top] = A[i];
 78     sort(B+1, B+1+top, cmp1);
 79     for(int i = 1; i <= top; i++){
 80         if(B[i].op) {
 81             bit[0].add(B[i].y1, B[i].op);
 82             bit[1].add(B[i].y2, B[i].op);
 83         }
 84         else {
 85             ans[B[i].id] += bit[0].tot - bit[0].query(B[i].y2);
 86             ans[B[i].id] += bit[1].query(B[i].y1-1);
 87         }
 88     }
 89     for(int i = 1; i <= top; i++){
 90         if(B[i].op) {
 91             bit[0].add(B[i].y1, -B[i].op);
 92             bit[1].add(B[i].y2, -B[i].op);
 93         }
 94     }
 95     sort(B+1, B+1+top, cmp2);
 96     for(int i = 1; i <= top; i++){
 97         if(B[i].op) {
 98             bit[0].add(B[i].y1, B[i].op);
 99             bit[1].add(B[i].y2, B[i].op);
100         }
101         else {
102             ans[B[i].id] += bit[0].tot - bit[0].query(B[i].y2);
103             ans[B[i].id] += bit[1].query(B[i].y1-1);
104         }
105     }
106     for(int i = 1; i <= top; i++){
107         if(B[i].op) {
108             bit[0].add(B[i].y1, -B[i].op);
109             bit[1].add(B[i].y2, -B[i].op);
110         }
111     }
112 }
113 int main(){
114     int n;
115     scanf("%d", &n);
116     int t = 0, tt = 0, num = 0, z;
117     for(int i = 1; i <= n; ++i){
118         scanf("%s", s);
119         if(s[0] == 'I'){
120             num++;
121             scanf("%d%d%d%d", &A[i].x1, &A[i].y1, &A[i].x2, &A[i].y2);
122             x[++xsz] = A[i].x1; x[++xsz] = A[i].x2;
123             y[++ysz] = A[i].y1; y[++ysz] = A[i].y2;
124             A[i].op = 1;
125             tmp[++t] = i;
126         }
127         else if(s[0] == 'D'){
128             num--;
129             scanf("%d", &z);
130             A[i] = A[tmp[z]];
131             A[i].op = -1;
132         }
133         else {
134             ++tt;
135             scanf("%d%d%d%d", &A[i].x1, &A[i].y1, &A[i].x2, &A[i].y2);
136             x[++xsz] = A[i].x1; x[++xsz] = A[i].x2;
137             y[++ysz] = A[i].y1; y[++ysz] = A[i].y2;
138             A[i].op = 0;A[i].id = tt;
139             ans[tt] = num;
140         }
141     }
142     sort(x+1, x+xsz+1); sort(y+1, y+ysz+1);
143     xsz = unique(x+1, x+1+xsz) - x - 1;
144     ysz = unique(y+1, y+1+ysz) - y - 1;
145     for(int i = 1; i <= n; i++){
146         A[i].x1 = lower_bound(x+1, x+1+xsz, A[i].x1) - x;
147         A[i].x2 = lower_bound(x+1, x+1+xsz, A[i].x2) - x;
148         A[i].y1 = lower_bound(y+1, y+1+ysz, A[i].y1) - y;
149         A[i].y2 = lower_bound(y+1, y+1+ysz, A[i].y2) - y;
150         if(A[i].op){
151             bit[0].add(A[i].x1, A[i].op);
152             bit[1].add(A[i].x2, A[i].op);
153             bit[2].add(A[i].y1, A[i].op);
154             bit[3].add(A[i].y2, A[i].op);
155         }
156         else {
157             num = ans[A[i].id];
158             ans[A[i].id] -= num - bit[0].query(A[i].x2);
159             ans[A[i].id] -= bit[1].query(A[i].x1-1);
160             ans[A[i].id] -= num - bit[2].query(A[i].y2);
161             ans[A[i].id] -= bit[3].query(A[i].y1-1);
162         }
163     }
164     for(int i = 0; i < 4; i++) bit[i].Clear();
165     cdq(1, n);
166     for(int i = 1; i <= tt; i++)
167         printf("%d\n", ans[i]);
168     return 0;
169 }
View Code

 

posted @ 2018-10-11 15:43  Schenker  阅读(298)  评论(0编辑  收藏  举报