您的位置:首页 > 大数据 > 人工智能

hdu5618Jam's problem again (CDQ分治)

2017-10-12 08:59 561 查看


Jam's problem again

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1417    Accepted Submission(s): 504


Problem Description

Jam like to solve the problem which on the 3D-axis,given N(1≤N≤100000) points (x,y,z)(1≤x,y,z≤100000)

If two point such as (xi,yi,zi) and (xj,yj,zj) xi≥xj yi≥yj zi≥zj,
the bigger one level add 1

Ask for the each level of the point.

 

Input

The first line is T(1≤T≤15) means T Case

For each case

The first line is N means
the number of Point and next there are N line,
each line has (x,y,z)

 

Output

Output with N line,each line has one number means the lever of point

 

Sample Input

1
4
10 4 7
10 6 6
8 2 5
7 3 10

 

Sample Output

1
1
0
0

 

Source

BestCoder Round #70

 

Recommend

hujie   |   We have carefully selected several similar problems for you:  6216 6215 6214 6213 6212 

题目大意:求对于每个点,满足以下条件的点数 (xi,yi,zi) and (xj,yj,zj) xi≥xj yi≥yj zi≥zj 

题目思路

这个的话,我们还是像二维偏序一样。
先把第一维排序。

然后我们就可以忽略第一维的影响了。
对于任意i<=j,满足x[i]<=x[j]。

然后我们还是采用归并的思路。

现在有两个有序的区间  [l,mid]
与 [mid+1,r]

那么我们开始计算左区间对右区间的贡献。

归并的时候我们有双指针。

假设a是左区间指针的当前位置 b是右区间当前指针的当前位置。

需要对z的权值建立一颗树状数组

双指针开始扫。

① a.y<b.y的话。把  add(a.z,1) 

a弹出,因为a对b及b以后的都有可能有贡献。


a.y>b.y 的话 b这个点的贡献 += Getsum(b.z)   

b弹出
,因为a及a后面的都不可能对b有贡献了。

细节:注意处理一下两点重合的情况。

代码实现

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define lowerbit(x) x&-x

struct Point
{
int x,y,z,id,cnt;
bool operator == (const Point& t)
{
if(x==t.x&&y==t.y&&z==t.z) return true;
return false;
}
}query[maxn],tmp[maxn],initarr[maxn];

int ans[maxn],sum[maxn],cnt,same,maxz;

bool cmp(const Point& a,const Point& b)//横坐标为第一维,排序。
{
if(a.x<b.x) return true;
if(a.x>b.x) return false;
if(a.y<b.y) return true;
if(a.y>b.y) return false;
if(a.z<b.z) return true;
if(a.z>b.z) return false;
return a.id<b.id;
}

void Update(int pos,int val)
{
while(pos<maxz+1)
{
sum[pos]+=val;
pos+=lowerbit(pos);
}
}

int Getsum(int pos)
{
int res=0;
while(pos>0)
{
res+=sum[pos];
pos-=lowerbit(pos);
}
return res;
}

void Clrtree(int pos)//清空树状数组
{
while(pos<maxz+1)
{
sum[pos]=0;
pos+=lowerbit(pos);
}
}

void CDQ(int l,int r)
{
if(l>=r) return;
int mid=(l+r)>>1;
CDQ(l,mid);
CDQ(mid+1,r);
int p=l,q=mid+1,o=0;
while(p<=mid&&q<=r)
{
if(query[p].y<=query[q].y)
{
Update(query[p].z,query[p].cnt);
tmp[o++]=query[p++];
}
else
{
ans[query[q].id]+=Getsum(query[q].z);
tmp[o++]=query[q++];
}
}
while(p<=mid) tmp[o++]=query[p++];
while(q<=r)
{
ans[query[q].id]+=Getsum(query[q].z);
tmp[o++]=query[q++];
}
for(int i=l;i<=mid;i++) Clrtree(query[i].z);
for(int i=0;i<o;i++) query[i+l]=tmp[i];
}

void Setans(int n)//处理重复的
{
for(int i=n-2;i>=0;i--)
if(initarr[i]==initarr[i+1])
ans[initarr[i].id]=ans[initarr[i+1].id];
}

int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
memset(ans,0,sizeof(ans));
memset(sum,0,sizeof(sum));
scanf("%d",&n);
maxz=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&initarr[i].x,&initarr[i].y,&initarr[i].z);
initarr[i].id=i;//记录初始位置,便于输出答案。
initarr[i].cnt=1;
maxz=max(maxz,initarr[i].z);
}
sort(initarr,initarr+n,cmp);
for(int i=0;i<n;i++) query[i]=initarr[i];
CDQ(0,n-1);//左闭右闭区间
Setans(n);//去重的东西重新覆盖
for(int i=0;i<n;i++) printf("%d\n",ans[i]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CDQ分治 hdu5618