国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

HDU - 5618 CDQ分治 + 樹狀數組

2019-11-11 00:27:19
字體:
來源:轉載
供稿:網友

題意:

給出n個有序對(a,,b,c),對于每個(ai,bi,ci)找到滿足aj <=ai,bj<=bi,cj<=ci的有序對有多少個。

思路:

典型的三維偏序問題,可以用CDQ分治來解決。首先將有序對按照a的大小排序,這樣對區間[L,R)進行分治的時候就可以默認左半部分[L,M)的a要小于等于右半部份[M,R)的a。按照CDQ分治的思想,先遞歸處理左右兩個部分的子問題,然后處理左半部分對于右半部份的影響,就這題來說,就是對左右兩部分按照b的大小排序,按照歸并排序的寫法先進入臨時數組tmp的有序對b一定不大于之后進的。那么現在關鍵是處理c,因為有c存在不能直接計數,注意到所有數字的大小只有1e5,這時候考慮用樹狀數組求和來統計c的個數,就如同求逆序對的作法一樣。對于左半部分的每一個有序對在來更新樹狀數組,右半部份的每個有序對來查詢樹狀數組,從而計數。這題還有幾個地方需要注意:1.定義Query大小關系的時候,要記得包括小于等于的情況。2.排序的時候不能只按照a的大小排序,還要按照先b后c確定優先級,因為這樣才能保證右邊區間的有序對能找到所有比優先級他小的。3.按照上面的做法,如果有m個完全一樣的有序對(a,b,c),這m個有序對所求的結果受到位置的影響并不一樣,因為排在后面的可以統計前面的,而前面的卻沒有統計后面的,所以一開始排序排在m個中最后的那個有序對才是這m個有序對共同的答案。4.記得在每一次的分治都要清空樹狀數組。

代碼:

#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5 + 10;const int MAXC = 1e5 + 10;const int MAXQ = MAXN;int maxc;struct BIT {    int C[MAXC];    int lowbit(int x) {        return x & -x;    }    void add(int x, int y) {        while (x <= MAXC) {            C[x] += y;            x += lowbit(x);        }    }    int sum(int x) {        int res = 0;        while (x) {            res += C[x];            x -= lowbit(x);        }        return res;    }     void clr(int x){         while (x <= MAXC) {             if (C[x]) C[x] = 0; else break;             x += lowbit(x);          }     }}bit;struct Query {    int id, b, c;    bool Operator < (const Query &rhs) const {        return b == rhs.b ? c <= rhs.c : b < rhs.b;    // 優先級一定要考慮到等于的情況    }}que[MAXQ], tmp[MAXQ];int ans[MAXN];void cdq(int l, int r) {    if (r - l <= 1) return;    int m = (l + r) >> 1;    cdq(l, m); cdq(m, r);    int p = l, q = m, cnt = 0;    while (p < m && q < r) {        if (que[p] < que[q]) {            bit.add(que[p].c, 1);            tmp[cnt++] = que[p++];        }        else {            ans[que[q].id] += bit.sum(que[q].c);            tmp[cnt++] = que[q++];        }    }    while (p < m) tmp[cnt++] = que[p++];    while (q < r) {        ans[que[q].id] += bit.sum(que[q].c);        tmp[cnt++] = que[q++];    }    for (int i = 0; i < cnt; i++) {        bit.clr(tmp[i].c);        que[i + l] = tmp[i];    }}struct node {    int id, a, b, c;    bool operator < (const node &rhs) const {        return a == rhs.a ? (b == rhs.b ? c < rhs.c : b < rhs.b) : a < rhs.a;   // 考慮位置因素,要按照先a再b后c的優先級排序    }}arr[MAXN];int main() {    //freopen("in.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--) {        int n;        scanf("%d", &n);        for (int i = 0; i < n; i++) {            scanf("%d%d%d", &arr[i].a, &arr[i].b, &arr[i].c);            arr[i].id = i;        }        sort (arr, arr + n);        maxc = 0;        for (int i = 0; i < n; i++) {            que[i] = (Query) {arr[i].id, arr[i].b, arr[i].c};            maxc = max(maxc, arr[i].c);        }        memset(ans, 0, sizeof(ans));        cdq(0, n);        for (int i = n - 1; i >= 0; i--) {            if (arr[i].a == arr[i + 1].a && arr[i].b == arr[i + 1].b && arr[i].c == arr[i + 1].c)                ans[arr[i].id] = ans[arr[i + 1].id];        // 倒著更新相同有序對的答案        }        for (int i = 0; i < n; i++)            PRintf("%d/n", ans[i]);    }    return 0;}
上一篇:poj1250

下一篇:349. Intersection of Two Arrays

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄大仙区| 东安县| 岳池县| 武宣县| 安徽省| 洛扎县| 体育| 比如县| 永泰县| 芒康县| 大同市| 八宿县| 伊金霍洛旗| 弥渡县| 江西省| 龙胜| 玉屏| 白河县| 新蔡县| 西乡县| 怀来县| 惠州市| 土默特右旗| 天水市| 华池县| 芒康县| 双鸭山市| 孝义市| 长武县| 汽车| 抚远县| 历史| 西安市| 庄河市| 涞源县| 阳高县| 辽阳县| 隆化县| 沂水县| 当阳市| 水富县|