[Bzoj3262]陌上花开(CDQ分治&&树状数组||树套树)

题目链接

题目就是赤裸裸的三维偏序,所以用CDQ+树状数组可以比较轻松的解决,但是还是树套树好想QAQ

CDQ+树状数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll maxn = 200000 + 100;
struct node {
    int a, b, c, num, val;
}q[maxn], w[maxn];
bool cmp(node x, node y) {
    return x.a == y.a ? (x.b == y.b ? x.c < y.c : x.b < y.b) : x.a < y.a;
}
int sum[maxn], ans[maxn];
int n, k;
int lowbit(int x) {
    return x & -x;
}
void add(int x, int val) {
    while (x <= k) {
        sum[x] += val;
        x += lowbit(x);
    }
}
int query(int x) {
    int ans = 0;
    while (x > 0) {
        ans += sum[x];
        x -= lowbit(x);
    }
    return ans;
}
void CDQ(int l, int r) {
    if (l == r)return;
    int mid = l + r >> 1;
    CDQ(l, mid); CDQ(mid + 1, r);
    int L = l, R = mid + 1, cnt = l;
    while (L <= mid && R <= r) {
        if (w[L].b <= w[R].b)add(w[L].c, w[L].num), q[cnt++] = w[L++];
        else w[R].val += query(w[R].c), q[cnt++] = w[R++];
    }
    while (L <= mid)add(w[L].c, w[L].num), q[cnt++] = w[L++];
    while (R <= r)w[R].val += query(w[R].c), q[cnt++] = w[R++];
    for (int i = l; i <= mid; i++)add(w[i].c, -w[i].num);
    for (int i = l; i <= r; i++)w[i] = q[i];
}
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &q[i].a, &q[i].b, &q[i].c), q[i].num = 1;
    sort(q + 1, q + 1 + n, cmp);
    int cnt = 1;
    w[1] = q[1];
    for (int i = 2; i <= n; i++) {
        if (q[i].a == w[cnt].a&&q[i].b == w[cnt].b&&q[i].c == w[cnt].c)w[cnt].num++;
        else w[++cnt] = q[i];
    }
    CDQ(1, cnt);
    for (int i = 1; i <= cnt; i++)
        ans[w[i].val + w[i].num - 1] += w[i].num;
    for (int i = 0; i < n; i++)
        printf("%d\n", ans[i]);
}

 

树套树(树状数组套线段树)

因为空间有限,线段树要动态开点且要写成链表QAQ。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef unsigned long long ull;
 5 const ll maxn = 200000 + 100;
 6 struct node {
 7     int a, b, c, num, val;
 8 }q[maxn], w[maxn];
 9 bool cmp(node x, node y) {
10     return x.a == y.a ? (x.b == y.b ? x.c < y.c : x.b < y.b) : x.a < y.a;
11 }
12 int n, k;
13 int ans[maxn];
14 struct seg {
15     struct node {
16         int  val;
17         node *ls, *rs;
18         node() { val = 0; ls = rs = NULL; }
19     };
20     node *root;
21     seg() {
22         root = NULL;
23     }
24     void update(node *&x, int pos, int val, int l, int r) {
25         if (!x)x = new node();
26         if (l == r) {
27             x->val += val;
28             return;
29         }
30         int mid = l + r >> 1;
31         if (pos <= mid)update(x->ls, pos, val, l, mid);
32         else update(x->rs, pos, val, mid + 1, r);
33         x->val = (x->ls ? x->ls->val : 0) + (x->rs ? x->rs->val : 0);
34     }
35     int query(node *x, int L, int R, int l, int r) {
36         if (!x)return 0;
37         if (L <= l && r <= R)
38             return x->val;
39         int mid = l + r >> 1, ans = 0;
40         if (L <= mid)ans += query(x->ls, L, R, l, mid);
41         if (R > mid)ans += query(x->rs, L, R, mid + 1, r);
42         return ans;
43     }
44 }T[maxn];
45 int lowbit(int x) {
46     return x & -x;
47 }
48 void add(int x, int q, int val) {
49     while (x <= k) {
50         T[x].update(T[x].root, q, val, 1, k);
51         x += lowbit(x);
52     }
53 }
54 int query(int x, int q) {
55     int ans = 0;
56     while (x > 0) {
57         ans += T[x].query(T[x].root, 1, q, 1, k);
58         x -= lowbit(x);
59     }
60     return ans;
61 }
62 int main() {
63     scanf("%d%d", &n, &k);
64     for (int i = 1; i <= n; i++)
65         scanf("%d%d%d", &q[i].a, &q[i].b, &q[i].c), q[i].num = 1;
66     sort(q + 1, q + 1 + n, cmp);
67     int cnt = 1;
68     w[1] = q[1];
69     for (int i = 2; i <= n; i++) {
70         if (q[i].a == w[cnt].a&&q[i].b == w[cnt].b&&q[i].c == w[cnt].c)w[cnt].num++;
71         else w[++cnt] = q[i];
72     }
73     for (int i = 1; i <= cnt; i++) {
74         add(w[i].b, w[i].c, w[i].num);
75         int p = query(w[i].b, w[i].c);
76         ans[p] += w[i].num;
77     }
78     for (int i = 1; i <= n; i++)
79         printf("%d\n", ans[i]);
80 }

 

posted @ 2019-08-30 20:00  祈梦生  阅读(149)  评论(0编辑  收藏  举报