Regionals 2015 >> Europe - Northwestern >> 7429 - Guessing Camels【CDQ分治】


Europe - Northwestern >> 7429 - Guessing Camels


Regionals 2015 >> Europe - Northwestern >> 7429 - Guessing Camels【CDQ分治】_第1张图片

题目大意:给出3个n长度的序列,问绝对位置有几对。绝对位置比如(2,1)是一对,因为在这三个序列中2都在1的前面

题目思路:转化一下,如图所示
Regionals 2015 >> Europe - Northwestern >> 7429 - Guessing Camels【CDQ分治】_第2张图片

2:在三个序列中出现的位置为(1,1,1)
3:在三个序列中出现的位置为(2,4,3)
位置记为(x,y,z)

如果要保证A的绝对位置在B的前面,那就是说要满足(x1 < x2,y1 < y2,y3 < y3),这就转化为了一个经典的三维偏序问题。可以用CDQ分治的方法解决。

(然而只会套用模板,待看懂。。)

类似的题目可参考:HDU-5618

以下是代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
/*
 * 三维偏序-CDQ分治
 * 数组下标从1开始
 */
#define N 200010
#define INF  0x3f3f3f3f
struct Point {
    int x, y, z;
    int id, sum;
    bool operator< (const Point& p) const {
        if(x != p.x) return x < p.x;
        if(y != p.y) return y < p.y;
        return z < p.z;
    }
    bool operator==(const Point& p) const {
        return x == p.x && y == p.y && z == p.z;
    }
} p[N];

struct BIT {
    int b[N];
    void init() {
        memset(b, 0, sizeof(b));
    }
    void add(int i, int v) {
        for(; i <= N; i += i & -i) b[i] += v;
    }
    int sum(int i) {
        int ret = 0;
        for(; i; i -= i & -i) ret += b[i];
        return ret;
    }
} bit;

bool cmpy(Point a, Point b) {
    return a.y < b.y;
}

void cdq(int l, int r) {
    if(l == r) return;
    int m = (l + r) >> 1;
    cdq(l, m);
    cdq(m + 1, r);
    sort(p + l, p + m + 1, cmpy);
    sort(p + m + 1, p + r + 1, cmpy);
    int j = l;
    for(int i = m + 1; i <= r; ++i) {
        for(; j <= m && p[j].y <= p[i].y; ++j) bit.add(p[j].z, 1);
        p[i].sum += bit.sum(p[i].z);
    }
    for(int i = l; i < j; ++i) bit.add(p[i].z, -1);
}

int n;
int ans[N];
vector <int> pos[N];
int main() {
    while(cin >> n) { 
        bit.init(); 
        for (int i = 0; i < 4; i++) pos[i].clear();
        for (int i = 0; i < 3; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                int num;
                cin >> num;
                pos[num].push_back(j);
            }
        }
        for (int i = 1; i <= n; i++)
        {
            p[i].x = pos[i][0];
            p[i].y = pos[i][1];
            p[i].z = pos[i][2];
            p[i].sum = 0;
            p[i].id = i;
        }
        sort(p + 1, p + n + 1);
        cdq(1,n);
        sort(p + 1, p + n + 1);
        long long last = 0;
        for(int i = 1, j; i <= n; ++i)
        {
            int maxv = -INF;
            for(j = i; j <= n && p[j] == p[i]; ++j) maxv = max(maxv, p[j].sum);
            for(j = i; j <= n && p[j] == p[i]; ++j) ans[p[j].id] = maxv;
            i = j - 1;
        }
        for (int i = 1; i <= n; i++) last += ans[i];
        cout << last << endl;
    }
    return 0;
}

你可能感兴趣的:(Regionals,ACM解题报告,CDQ分治)