HDU 5618 Jam's problem again (cdq分治+树状数组)

题目链接:点击打开链接

题意:给n个点,求每一个点的满足xyz都小于等于它的其他点的个数。

思路:经典的cdq分治+树状数组。  方法就是先按照x从小到大排序, 这样,x一定满足后面的大于等于前面的, 这样我们就可以不用管x了, 然后对y进行cdq分治,使得y满足关系, 在此基础上用树状数组顺便维护z坐标。  但是由于cdq分治每次总是要解决左边对右边的影响, 所以在相等时, 每次只更新了右边的点。  因此预处理一下相等的情况。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 100000 + 10;
int T,n,m,bit[maxn],maxd,res[maxn];
struct node {
    int x, y, z, id;
    node(int x=0, int y=0, int z=0, int id=0):x(x),y(y),z(z),id(id) {}
}a[maxn],b[maxn];
int sum(int x) {
    int ans = 0;
    while(x > 0) {
        ans += bit[x];
        x -= x & -x;
    }
    return ans;
}
void add(int x, int d) {
    while(x <= maxd) {
        bit[x] += d;
        x += x & -x;
    }
}
bool cmp1(node a, node b) {
    if(a.x != b.x) return a.x < b.x;
    else if(a.y != b.y) return a.y < b.y;
    else return a.z < b.z;
}
bool cmp2(node a, node b) {
    if(a.y != b.y) return a.y < b.y;
    else return a.id < b.id;
}
void cdq(int l, int r) {
    if(l == r) return ;
    int m = (l + r) >> 1;
    int cc = 0;
    for(int i=l;i<=m;i++) b[cc++] = node(0, a[i].y, a[i].z, 0);
    for(int i=m+1;i<=r;i++) b[cc++] = node(0, a[i].y,a[i].z,a[i].id);
    sort(b, b+cc, cmp2);
    for(int i=0;i<cc;i++) {
        if(b[i].id == 0) {
            add(b[i].z, 1);
        }
        else {
            res[b[i].id] += sum(b[i].z);
        }
    }
    for(int i=0;i<cc;i++) {
        if(b[i].id == 0) add(b[i].z, -1);
    }
    cdq(l, m);
    cdq(m+1, r);
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        maxd = 0;
        for(int i=1;i<=n;i++) {
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
            a[i].id = i;
            maxd = max(maxd, a[i].z);
        }
        sort(a+1, a+n+1, cmp1);
        memset(res, 0, sizeof(int)*(n+5));
        int cnt = 0;
        for(int i=n;i>=1;i--) {
            if(a[i].x == a[i+1].x && a[i].y == a[i+1].y && a[i].z == a[i+1].z) cnt++;
            else cnt = 0;
            res[a[i].id] += cnt;
        }
        cdq(1, n);
        for(int i=1;i<=n;i++) {
            printf("%d\n",res[i]);
        }
    }
    return 0;
}


你可能感兴趣的:(HDU,BestCoder,ACM-ICPC)