CDQ example partition notes +

CDQ partition is an offline divide and conquer algorithm, which partition the operation sequence based on the time sequence.

See such a problem: In a three dimensional coordinate system, there are a number of points, each point has coordinates corresponding to \ ((X_i, Y_i, Z_i) \) , we have to meet all requirements for each point \ (X_j < = X_i, Y_j <= Y_i, Z_j <= Z_i \) number of j.

Consider how to do on a two-dimensional plane: We can all point in accordance with the X coordinate of the sort, and then a tree-like array or other data structure maintenance Y coordinates of each point to read a statistic the answer, then this point join tree array. This while ensuring X, Y coordinates satisfy the condition.

If more then one-dimensional, then we have no way of sorting this way, according to the one-dimensional ordering is bound to upset the other two dimensions. Then we consider the CDQ partition, press the X coordinate of the sort, then the sequence is divide and conquer, each about two scripts separation sequence, then we can see, the left X coordinate of each point in the sequence is less than the midpoint of the right sequence X coordinate, then the left and right sequences are sorted by Y coordinate. When the answer to statistics, only the right to update the midpoint of the sequence of answers, only added to the sequence of points left in the tree array.

Template: P3810 [template] three-dimensional partial order (Mo flowers)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 100005;
const int M = 200005;
int C[M], n, maxk, nn, ans[N];
struct node {
    int a, b, c, tot, num;
} e[N];
int lowbit(int x) {
    return x & -x;
}
void add(int x, int k) {
    for(; x <= maxk; x += lowbit(x)) C[x] += k;
}
int query(int x) {
    int answ = 0; 
    for(; x; x -= lowbit(x)) answ += C[x];
    return answ;
}
bool cmp1(node x, node y) {
    if(x.a == y.a && x.b == y.b) return x.c < y.c;
    if(x.a == y.a) return x.b < y.b;
    return x.a < y.a;
}
void cdq(int l, int r) {
    int mid = (l + r) >> 1;
    if(l != mid) cdq(l, mid);
    if(mid + 1 != r) cdq(mid + 1, r);
    node p[N]; 
    int pt = 0, i = l, j = mid + 1;
    while(i <= mid && j <= r) {//对于第二维归并排序
        if(e[i].b <= e[j].b) add(e[i].c, e[i].tot), p[++pt] = e[i++];//插入
        else e[j].num += query(e[j].c), p[++pt] = e[j++];//更新答案
    }
    while(i <= mid) add(e[i].c, e[i].tot), p[++pt] = e[i++];
    while(j <= r) e[j].num += query(e[j].c), p[++pt] = e[j++];
    for(int t = l; t <= mid; t++) add(e[t].c, -e[t].tot);//树状数组清空
    for(int t = 1, u = l; t <= pt && u <= r; t++, u++) e[u] = p[t];//更新序列
}
int main() {
//  freopen("data.in", "r", stdin);
    scanf("%d%d", &nn, &maxk);
    for(int i = 1, a, b, c; i <= nn; i++) {
        scanf("%d%d%d", &a, &b, &c);
        e[i].a = a, e[i].b = b, e[i].c = c;
        e[i].num = 0; e[i].tot = 1;
    }
    sort(e + 1, e + 1 + nn, cmp1);//先按照第一维排序
    n = 1;
    for(int i = 2; i <= nn; i++) {
        if(e[i].a == e[n].a && e[i].b == e[n].b && e[i].c == e[n].c) e[n].tot++;
        else e[++n] = e[i];
    }
    cdq(1, n); 
    for(int i = 1; i <= n; i++) {
        ans[e[i].num + e[i].tot - 1] += e[i].tot;
    }
    for(int i = 0; i < nn; i++) printf("%d\n", ans[i]);
    return 0;
}

Example. 1: P3157 [CQOI2011] Dynamic reverse order

Consider such as the number and convert it into a three-dimensional partial order problem, we have to calculate delete a point to answer to the contribution that the number and the right ratio of its major point of the left point to remove smaller than his point, so three-dimensional, respectively deletion order, sequence position, element size.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long lld;
const int N = 100005;
const int M = 50005;
int n, m, pos[N], ansper[N], ansnxt[N];
struct node {
   int x, y, type;
} e[N], a[N];
int C[N];
int lowbit(int x) {
   return x & -x;
}
void add(int x, int k) {
   for(; x < N; x += lowbit(x)) C[x] += k;
}
int query(int x) {
   int summ = 0;
   for(; x; x -= lowbit(x)) summ += C[x];
   return summ;
}
void cdq_per(int l, int r) {
   if(l == r) return ;
   int mid = (l + r) >> 1;
   cdq_per(l, mid); cdq_per(mid + 1, r);
   node p[N];
   int i = l, j = mid + 1, pt = 0;
   while(i <= mid && j <= r) {
       if(e[i].x <= e[j].x) add(e[i].y, 1), p[++pt] = e[i++];
       else {
           if(e[j].type == 0) p[++pt] = e[j++];
           else ansper[e[j].type] += query(N - 1) - query(e[j].y), p[++pt] = e[j++];
       }
   }
   while(i <= mid) add(e[i].y, 1), p[++pt] = e[i++];
   while(j <= r) {
       if(e[j].type == 0) p[++pt] = e[j++];
       else ansper[e[j].type] += query(N - 1) - query(e[j].y), p[++pt] = e[j++];
   }
   for(int k = l; k <= mid; k++) add(e[k].y, -1);
   for(int t = 1, u = l; t <= pt && u <= r; t++, u++) e[u] = p[t];
}
void cdq_nxt(int l, int r) {
   if(l == r) return ;
   int mid = (l + r) >> 1;
   cdq_nxt(l, mid); cdq_nxt(mid + 1, r);
   node p[N]; 
   int i = l, j = mid + 1, pt = 0;
   while(i <= mid && j <= r) {
       if(a[i].x <= a[j].x) add(a[i].y, 1), p[++pt] = a[i++];
       else {
           if(a[j].type == 0) p[++pt] = a[j++];
           else ansnxt[a[j].type] += query(a[j].y), p[++pt] = a[j++];
       }
   }
   while(i <= mid) add(a[i].y, 1), p[++pt] = a[i++];
   while(j <= r) {
       if(a[j].type == 0) p[++pt] = a[j++];
       else ansnxt[a[j].type] += query(a[j].y), p[++pt] = a[j++];
   }
   for(int k = l; k <= mid; k++) add(a[k].y, -1);
   for(int t = 1, u = l; t <= pt && u <= r; t++, u++) a[u] = p[t];
}
int main() {
//  freopen("data.in", "r", stdin);
   scanf("%d%d", &n, &m);
   for(int i = 1, x; i <= n; i++) {
       scanf("%d", &x);
       e[i].x = e[i].type = 0; e[i].y = x;
       pos[x] = i;
   }
   for(int i = 1, x; i <= m; i++) {
       scanf("%d", &x);
       e[pos[x]].x = m - i + 1;
       e[pos[x]].type = i;
   }
   for(int i = 1; i <= n; i++) a[i] = e[n - i + 1];
   cdq_per(1, n); 
   for(int i = 1; i <= n; i++) e[i] = a[n - i + 1];
   cdq_nxt(1, n);
   lld ans_sum = 0;
   for(int i = 1; i <= n; i++) {
       ans_sum += i - query(e[i].y) - 1; 
       add(e[i].y, 1);
   }
   int k = 1;
   while(k <= m) {
       printf("%lld\n", ans_sum); 
       ans_sum -= (ansper[k] + ansnxt[k]);
       k++;
   }
   return 0;
}

Example 2: P4169 [Violet] angel doll / SJY put the pieces

。。。。。

Guess you like

Origin www.cnblogs.com/mcggvc/p/12343912.html