[Luogu 3810]三维偏序

Description

有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i $ 、$ b_i $ 、$ c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ 且 $ b_j \leq b_i $ 且 $ c_j \leq c_i $ 的 $ j $ 的数量。

对于 $ d \in [0, n) $ ,求 $ f(i) = d $ 的数量

Input

第一行两个整数 $ n $ 、$ k $ ,分别表示元素数量和最大属性值。

之后 $ n $ 行,每行三个整数 $ a_i $ 、$ b_i $ 、$ c_i $ ,分别表示三个属性值。

Output

输出 $ n $ 行,第 $ d + 1 $ 行表示 $ f(i) = d $ 的 $ i $ 的数量。

Sample Input

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

Sample Output

3
1
3
0
1
0
1
0
0
1

Hint

$ 1 \leq n \leq 100000, 1 \leq k \leq 200000 $

题解

 $CDQ$ 分治模板题。

三维:

第一维 $sort$ 排序

第二维 $CDQ$

第三维 $bittree$

我们将第一维排序后,我们用递归实现 $CDQ$ ,取 $mid$ ,算出 $mid$ 左边对 $mid$ 右边的贡献。

用 $bittree$ 来维护最后一维的大小关系。

 

 1 #include<set>
 2 #include<map>
 3 #include<cmath>
 4 #include<ctime>
 5 #include<queue>
 6 #include<stack>
 7 #include<cstdio>
 8 #include<string>
 9 #include<vector>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 #define lowbit(x) ((x)&-(x))
15 using namespace std;
16 const int N=100000;
17 const int K=200000;
18 
19 struct point
20 {
21     int a,b,c,cnt,ans;
22 }g[N+5];
23 int n,m,ans[N+5],c[K+5],num;
24 bool cmp2(point x,point y) {return x.b==y.b ? x.c<y.c:x.b<y.b;}
25 bool cmp1(point x,point y) {return x.a==y.a ? cmp2(x,y):x.a<y.a;}
26 void Add(int x,int y) {for (;x<=m;x+=lowbit(x)) c[x]+=y;}
27 int Count(int x)
28 {
29     int r=0;
30     for (;x;x-=lowbit(x)) r+=c[x];
31     return r;
32 }
33 void CDQ(int l,int r)
34 {
35     if(l==r) return;
36     int mid=(l+r)>>1;
37     CDQ(l,mid);
38     CDQ(mid+1,r);
39     sort(g+l,g+mid+1,cmp2);
40     sort(g+mid+1,g+r+1,cmp2);
41     int t1=l,t2=mid+1;
42     while(t2<=r)
43     {
44         while(t1<=mid&&g[t1].b<=g[t2].b)
45         {
46             Add(g[t1].c,g[t1].cnt);
47             t1++;
48         }
49         g[t2].ans+=Count(g[t2].c);
50         t2++;
51     }
52     for (int i=l;i<=t1-1;i++) Add(g[i].c,-g[i].cnt);
53 }
54 int main()
55 {
56     scanf("%d%d",&n,&m);
57     for (int i=1;i<=n;i++) scanf("%d%d%d",&g[i].a,&g[i].b,&g[i].c),g[i].cnt=1;
58     sort(g+1,g+n+1,cmp1);
59     for (int i=1;i<=n;i++)
60     {
61         int k=i+1;
62         while(g[i].a==g[k].a&&g[i].b==g[k].b&&g[i].c==g[k].c) k++;
63         num++;
64         k--;
65         g[i].cnt+=k-i;
66         g[num]=g[i];
67         i=k;
68     }
69     CDQ(1,num);
70     for (int i=1;i<=num;i++) ans[g[i].ans+g[i].cnt-1]+=g[i].cnt;
71     for (int i=0;i<n;i++) printf("%d\n",ans[i]);
72     return 0;
73 }

 

posted @ 2017-08-21 20:09  NaVi_Awson  阅读(240)  评论(0编辑  收藏  举报