Jam's problem again

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

Total Submission(s): 640    Accepted Submission(s): 210

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
三维偏序,即要求一个三维的点比这个点的小的点有多少个。
如果是一维的我们可以怎么做呢?很简单排个序就可以了。
如果是二维的呢,同时要求x1<x2和y1<y2点(x1,y1)比点(x2,y2)小。我们可以想到二维树状数组可以
很高效率的解决这个问题,但是数据要是有10万,就开不来二维树状数组了。那么可以降维来做。
一维排序,二维用树状数组或者线段树来解决,也可以用CDQ分治来做。
例如用树状数组,那么按照x排序之后,在树状数组里插入y,边插入边询问,就可以n*logn的效率得到答案。
三维的情况呢,同理,第三维可以继续用树状数组或者线段树,但是用树状数组就相当于一个二维树状数组显然会超内存。
所以我们可以用动态线段树,不会超内存。
如果了用了CDQ分治,那么可以这样一维排序,二维CDQ分治,三维树状数组
也可以一维排序,二维CDQ分治,三维CDQ分治
一维排序,二维树状数组,三维线段树
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <stdlib.h> using namespace std;
typedef long long int LL;
const int maxn=1e5;
struct Node
{
int x,y,z;
int id;
int num;
}a[maxn+5];
int n;
int rt[maxn+5];
int ls[maxn*50];
int rs[maxn*50];
int sum[maxn*50];
int p;
int ans1,ans2;
int newnode()
{
ls[p]=rs[p]=sum[p]=0;
return p++;
}
int lowbit(int x)
{
return x&(-x);
}
int cmp(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;
}
}
int cmp2(Node a,Node b)
{
return a.id<b.id;
}
void insert(int &node,int l,int r,int tag)
{
if(!node)
node=newnode();
if(l==r)
{
sum[node]++;
return;
}
sum[node]++;
int mid=(l+r)>>1;
if(tag<=mid)
insert(ls[node],l,mid,tag);
else
insert(rs[node],mid+1,r,tag);
}
int query(int &node,int l,int r,int tag)
{
if(!node) return 0;
if(r<=tag)
{
return sum[node];
}
int mid=(l+r)>>1;
if(tag<=mid) return query(ls[node],l,mid,tag);
else return sum[ls[node]]+query(rs[node],mid+1,r,tag);
}
int find(int y,int z)
{
int res=0;
for(int i=y;i>=1;i-=lowbit(i))
{
res+=query(rt[i],1,ans2,z);
}
return res;
}
void update(int y,int z)
{
for(int i=y;i<=maxn;i+=lowbit(i))
{
insert(rt[i],1,ans2,z);
}
}
void init(int y,int z)
{
memset(rt,0,sizeof(rt));
for(int i=1;i<=y;i++)
{
rt[i]=i;
ls[i]=rs[i]=sum[i]=0;
}
p=y+1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ans1=0; ans2=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
ans1=max(ans1,a[i].y);
ans2=max(ans2,a[i].z);
a[i].id=i;a[i].num=0;
}
sort(a+1,a+n+1,cmp);
for(int i=n-1;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)
a[i].num=a[i+1].num+1;
} init(ans1,ans2);
for(int i=1;i<=n;i++)
{
a[i].num+=find(a[i].y,a[i].z);
update(a[i].y,a[i].z); }
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++)
{
printf("%d\n",a[i].num);
}
}
return 0;
}

一维排序,二维CDQ分治,三维树状数组

include <iostream>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <string.h> using namespace std;
typedef long long int LL;
const int maxn=1e5;
int n;
struct Node
{
int x,y,z;
int id;
int num;
}a[maxn+5],b[maxn+5];
int c[maxn+5];
int cmp(Node a,Node b)
{
if(a.x==b.x&&a.y==b.y)
return a.z<b.z;
if(a.x==b.x)
return a.y<b.y;
return a.x<=b.x;
}
int cmp2(Node a,Node b)
{
return a.id<b.id;
}
int lowbit(int x)
{
return x&(-x);
}
void insert(int x,int y)
{
for(int i=x;i<=maxn;i+=lowbit(i))
c[i]+=y;
}
int sum(int x)
{
int s=0;
for(int i=x;i>=1;i-=lowbit(i))
s+=c[i];
return s;
}
void fun(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
int j=l;
int k=mid+1;
fun(l,mid);
fun(mid+1,r);
for(int i=l;i<=r;i++)
{
if((a[j].y<=a[k].y||k>r)&&j<=mid)
{
b[i]=a[j++];
insert(b[i].z,1);
}
else
{
b[i]=a[k++];
b[i].num+=sum(b[i].z);
}
}
for(int i=l;i<=r;i++)
{
if(i<=mid)
insert(a[i].z,-1);
a[i]=b[i];
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(c,0,sizeof(c));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
a[i].id=i;a[i].num=0;
}
sort(a+1,a+n+1,cmp);
for(int i=n-1;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)
a[i].num=a[i+1].num+1;
}
fun(1,n);
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++)
{
printf("%d\n",a[i].num);
}
}
return 0;
}

一维排序,二维CDQ分治,三维CDQ分治

#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <stdlib.h> using namespace std;
typedef long long int LL;
const int maxn=1e5;
struct Node
{
int x,y,z;
int id,num;
int tag; }a[maxn+5],b[maxn+5],c[maxn+5];
int ans[maxn+5];
int n; int cmp(Node a,Node b)
{
if(a.x==b.x&&a.y==b.y)
return a.z<b.z;
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int cmp2(Node a,Node b)
{
return a.id<b.id;
}
void fun2(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
fun2(l,mid);
fun2(mid+1,r);
int j=l;
int k=mid+1;
int res=0;
for(int i=l;i<=r;i++)
{
if((b[j].z<=b[k].z||k>r)&&j<=mid)
{
c[i]=b[j++];
if(!c[i].tag)
res++;
}
else
{
c[i]=b[k++];
if(c[i].tag)
c[i].num+=res,ans[c[i].id]+=res;
}
}
for(int i=l;i<=r;i++)
b[i]=c[i];
}
void fun1(int l,int r)
{ if(l==r)
return;
int mid=(l+r)>>1;
fun1(l,mid);
fun1(mid+1,r);
int j=l;
int k=mid+1;
for(int i=l;i<=r;i++)
{
if((a[j].y<=a[k].y||k>r)&&j<=mid)
{
b[i]=a[j++];
b[i].tag=0;
}
else
{
b[i]=a[k++];
b[i].tag=1;
}
}
for(int i=l;i<=r;i++)
a[i]=b[i]; fun2(l,r); }
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
a[i].num=0;
a[i].tag=0;
a[i].id=i; }
memset(ans,0,sizeof(ans)); sort(a+1,a+n+1,cmp);
for(int i=n-1;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)
a[i].num=a[i+1].num+1,ans[a[i].id]=ans[a[i+1].id]+1; fun1(1,n);
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}



 

HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)的更多相关文章

  1. hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  2. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  3. HDU 3303 Harmony Forever 前缀和+树状数组||线段树

    Problem Description We believe that every inhabitant of this universe eventually will find a way to ...

  4. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  5. hdu 1166 树状数组(线段树)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  6. hdu 1166 敌兵布阵——(区间和)树状数组/线段树

    pid=1166">here:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Input 第一行一个整数T.表示有T组数据. 每组数据第一 ...

  7. HDU 1166 敌兵布阵 树状数组||线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=1166 题目大意: 给定n个数的区间N<=50000,还有Q个询问(Q<=40000)求区间和. 每个 ...

  8. HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp

    传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...

  9. hdu 1166 树状数组 线段树入门

    点修改 区间求和 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> ...

  10. Holedox Eating HDU - 4302 2012多校C 二分查找+树状数组/线段树优化

    题意 一个长度$n<=1e5$的数轴,$m<=1e5$个操作 有两种一些操作 $0$  $x$ 在$x$放一个食物 $1$ 一个虫子去吃最近的食物,如果有两个食物一样近,不转变方向的去吃 ...

随机推荐

  1. 74hc165三片级联

    3片74HC165进行级联,用于扩展IO口,读取外界设备的数据. unsigned int read_74165(void) { unsigned ; unsigned ; //三片74hc165,需 ...

  2. spring只是一个框架

    想跟着 spring in action 4 系统的研究下spring,结果发现忘了怎么建一个spring项目. 关键是,不知道该建一个什么项目,Java项目?Maven项目(Java项目?Web项目 ...

  3. 关于Java方法的参数

    刚好看到C++的函数这块,说C++中除了引用类型的形参,其他都是实参的副本(个人总结). 隐约记得Java中方法的参数也是这么回事,于是手动测试一番. 结果 Java中方法的参数都是值传递,哪怕是引用 ...

  4. 第二百八十八节,MySQL数据库-索引、limit分页、执行计划、慢日志查询

    MySQL数据库-索引.limit分页.执行计划.慢日志查询 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获 ...

  5. javascript -- js正则表达式

    正则表达式可以:  1.测试字符串的某个模式.例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式.这称为数据有效性验证 2.替换文本.可以在文档中使用一个正则 ...

  6. vnc 多用户登录

    1, 创建新用户: $ useradd tom $ passwd tom 2,  登录到tom账户,创建vnc实例: $ su tom$ vncserver 这时可以看看~/.vnc/目录下,有一些如 ...

  7. Oracle中的三种循环(For、While、Loop)

    from:http://jingyan.baidu.com/article/c275f6ba38036ae33c756773.html GOTO用法,以下是SQL源码: DECLARE  x numb ...

  8. 从spring容器中取出注入的bean

    从spring容器中取出注入的bean 工具类,代码如下: package com.hyzn.fw.util; import org.springframework.beans.BeansExcept ...

  9. Linux nmon 命令

    nmon 是一个资源监控工具,能够监控 Linux 系统资源( cpu,memory,network,disks )的使用情况,常见用法如下: [root@localhost ~]$ yum inst ...

  10. ios 图片处理( 1.按比例缩放 2.指定宽度按比例缩放

    本文转载至 http://blog.sina.com.cn/s/blog_6f29e81f0101tat6.html //按比例缩放,size 是你要把图显示到 多大区域 CGSizeMake(300 ...