HDU 5618 Jam's problem again CDQ分治 BC ROUND 70

题意:给你1e5个点(x,y,z),对于每一个点询问有多少个点(x1,y1,z1)满足x1<=x&&y1<=y&&z1<=z

分析:(官方题解奉上)很显然让你找(x,y,z)(x,y,z)都大于别的(x,y,z)(x,y,z),当然厉害的人可以用树套树水一下,但正解写的是CDQ分治,以xx为第一关键字排序,以yy为第二关键字来找,以zz为第三关键字建一个树状数组找就好了,当然等于的情况可以实现前做一下。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
struct BIT
{
    int c[maxn];
    void init()
    {
        memset(c,0,sizeof(c));
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x,int t)
    {
        while(x<=1e5)
        {
            c[x]+=t;
            x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int ans=0;
        while(x>0)
        {
            ans+=c[x];
            x-=lowbit(x);
        }
        return ans;
    }
} bit;
struct Node
{
    int x,y,z,id;
} o[maxn],tem[maxn];
bool cmp(Node a,Node b)
{
    if(a.x!=b.x)
    return a.x<b.x;
    if(a.y!=b.y)
     return a.y<b.y;
   return a.z<b.z;
}
bool cmp1(Node a,Node b)
{
    return a.y<b.y;
}
int res[maxn];
void solve(int l,int r)
{
    if(l==r)return;
    int m=(l+r)>>1;
    for(int i=l; i<=r; ++i)
        tem[i]=o[i];
    sort(tem+l,tem+m+1,cmp1);
    sort(tem+m+1,tem+r+1,cmp1);
    int cnt=l;
    for(int i=m+1; i<=r; ++i)
    {
        while(cnt<=m&&tem[cnt].y<=tem[i].y)bit.add(tem[cnt].z,1),cnt++;
        res[tem[i].id]+=bit.sum(tem[i].z);
    }
    for(int i=l; i<cnt; ++i)
        bit.add(tem[i].z,-1);
    solve(l,m);
    solve(m+1,r);
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        bit.init();
        for(int i=1; i<=n; ++i)
            scanf("%d%d%d",&o[i].x,&o[i].y,&o[i].z),o[i].id=i;
        sort(o+1,o+1+n,cmp);
        memset(res,0,sizeof(res));
        solve(1,n);
        for(int i=n-1; i>0; --i)
            if(o[i].x==o[i+1].x&&o[i].y==o[i+1].y&&o[i].z==o[i+1].z)
                res[o[i].id]=res[o[i+1].id];
        for(int i=1; i<=n; ++i)
            printf("%d\n",res[i]);
    }
    return 0;
}
View Code

 

你可能感兴趣的:(HDU 5618 Jam's problem again CDQ分治 BC ROUND 70)