P3810 【模板】三维偏序(陌上花开)

题目描述

有 nn 个元素,第 ii 个元素有 a_iaib_ibic_ici 三个属性,设 f(i)f(i) 表示满足 a_j leq a_iajai 且 b_j leq b_ibjbi 且 c_j leq c_icjci的 jj 的数量。

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

输入输出格式

输入格式:

 

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

之后 nn 行,每行三个整数 a_iaib_ibic_ici,分别表示三个属性值。

 

输出格式:

 

输出 nn 行,第 d + 1d+1 行表示 f(i) = df(i)=d 的 ii 的数量。

 

输入输出样例

输入样例#1: 复制
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
输出样例#1: 复制
3
1
3
0
1
0
1
0
0
1

说明

1 leq n leq 100000, 1 leq k leq 2000001n100000,1k200000




就是一维排序,一维cdq,一维数据结构,

然后就是要把萨格属性完全相同的要去掉,并在这个属性的个数上+1. 其他的就没什么了

其实一开始看到cdq是一脸懵逼的,怎么看也看不懂,但是理解了以后就会发现这玩意也挺简单的。



 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 struct point{
 6     int a,b,c,id;
 7     point(){
 8         a=b=c=id=0;
 9     }
10 }num[100001],tem[100001];
11 bool cmp(point lhs,point rhs){
12     if(lhs.a!=rhs.a)return lhs.a<rhs.a;
13     if(lhs.b!=rhs.b)return lhs.b<rhs.b;
14     return lhs.c<rhs.c;
15 }
16 int c[200001],ans[100001],fin[100001],size[100001];
17 int n,k;
18 void update(int ind,int num){for(;ind<=k;ind+=ind&-ind)c[ind]+=num;}
19 long long query(int ind){
20     long long tot=0;
21     for(;ind;ind-=ind&-ind)tot+=c[ind];
22     return tot;
23 }
24 void cdq(int l,int r){
25     if(l==r)return;
26     int mid=(l+r)/2;
27     cdq(l,mid);cdq(mid+1,r);
28     int i=l,j=mid+1,ind=l;
29     while(i<=mid&&j<=r){
30         if(num[i].b<=num[j].b)update(num[i].c,size[num[i].id]),tem[ind++]=num[i++];
31         else ans[num[j].id]+=query(num[j].c),tem[ind++]=num[j++];
32     }
33     while(j<=r)ans[num[j].id]+=query(num[j].c),tem[ind++]=num[j++];
34     for(int e=l;e<i;e++)update(num[e].c,-size[num[e].id]);
35     while(i<=mid)tem[ind++]=num[i++];
36     for(int i=l;i<=r;i++)num[i]=tem[i];
37 }
38 int main(){
39     scanf("%d%d",&n,&k);
40     for(int i=1;i<=n;i++)scanf("%d%d%d",&num[i].a,&num[i].b,&num[i].c);
41     std::sort(num+1,num+n+1,cmp);
42     int ind=0;
43     for(int i=1;i<=n;i++){
44         if(num[i].a!=num[i-1].a||num[i].b!=num[i-1].b||num[i].c!=num[i-1].c)tem[++ind]=num[i];
45         size[ind]++;
46     }
47     for(int i=1;i<=ind;i++)num[i]=tem[i],num[i].id=i;
48     cdq(1,ind);
49     for(int i=1;i<=ind;i++)fin[ans[num[i].id]+size[num[i].id]-1]+=size[num[i].id];
50     for(int i=0;i<n;i++)printf("%d
",fin[i]);
51 }
原文地址:https://www.cnblogs.com/zhangbuang/p/10425895.html