CDQ分治 P3810 【模板】三维偏序(陌上花开)
题目背景
这是一道模板题
可以使用bitset,CDQ分治,K-DTree等方式解决。
题目描述
有 n 个元素,第 i个元素有 ai、bi、ci 三个属性,设 f(i)f表示满足aj≤ai 且bj≤bi 且 cj≤ci 的 j的数量。
对于 d∈[0,n),求 f(i)=d 的数量
输入格式
第一行两个整数 n、k,分别表示元素数量和最大属性值。
之后 n 行,每行三个整数 ai、bi、ci,分别表示三个属性值。
输出格式
输出 n行,第 d + 1行表示 f(i) = d的 i 的数量。
输入输出样例
输入 #110 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输出 #13 1 3 0 1 0 1 0 0 1说明/提示
1≤n≤100000,1≤k≤200000
板子题,思想类似于归并排。
1 // luogu-judger-enable-o2 2 #include<bits/stdc++.h> 3 #define re register int 4 #define lowbit(x) x&(-x) 5 #define LL long long 6 const int maxn1=100000+5; 7 const int maxn2=200000+5; 8 using namespace std; 9 int tree[maxn2]; 10 int cnt[maxn2]; 11 int n,k; 12 inline int read() 13 { 14 int x=0,f=1; 15 char ch=getchar(); 16 while(!isdigit(ch)) 17 { 18 if(ch=='-') f=-1; 19 ch=getchar(); 20 } 21 while(isdigit(ch)) 22 { 23 x=(x<<3)+(x<<1)+ch-'0'; 24 ch=getchar(); 25 } 26 return x*f; 27 } 28 inline void write(int x) 29 { 30 if(x<0) 31 { 32 putchar('-'); 33 x=-x; 34 } 35 if(x>9) write(x/10); 36 putchar(x%10+'0'); 37 } 38 struct node{ 39 int x,y,z,ans,w; 40 }; 41 node no[maxn1],ed[maxn1]; 42 bool cmpx(const node &a,const node&b) 43 { 44 if(a.x!=b.x) return a.x<b.x; 45 if(a.y!=b.y) return a.y<b.y; 46 else return a.z<b.z; 47 } 48 bool cmpy(const node &a,const node&b) 49 { 50 if(a.y!=b.y) return a.y<b.y; 51 else return a.z<b.z; 52 } 53 void add(int pos,int val) 54 { 55 while(pos<=k) 56 { 57 tree[pos]+=val; 58 pos+=lowbit(pos); 59 } 60 } 61 int Query(int pos) 62 { 63 int ans=0; 64 while(pos) 65 { 66 ans+=tree[pos]; 67 pos-=lowbit(pos); 68 } 69 return ans; 70 } 71 void cdq(int l,int r) 72 { 73 if(l==r) return; 74 int mid=(l+r)>>1; 75 cdq(l,mid); 76 cdq(mid+1,r); 77 sort(no+l,no+mid+1,cmpy); 78 sort(no+mid+1,no+r+1,cmpy); 79 int i=mid+1,j=l; 80 for(;i<=r;i++) 81 { 82 while(no[j].y<=no[i].y&&j<=mid) 83 { 84 add(no[j].z,no[j].w); 85 j++;} 86 no[i].ans+=Query(no[i].z); 87 } 88 for(i=l;i<j;i++) 89 add(no[i].z,-no[i].w); 90 } 91 int cou; 92 int main() 93 { 94 n=read(); 95 k=read(); 96 for(re i=1;i<=n;i++) 97 { 98 ed[i].x=read(); 99 ed[i].y=read(); 100 ed[i].z=read(); 101 } 102 sort(ed+1,ed+n+1,cmpx); 103 int sum=0; 104 for(re i=1;i<=n;i++) 105 { 106 sum++; 107 if(ed[i].x!=ed[i+1].x||ed[i].y!=ed[i+1].y||ed[i].z!=ed[i+1].z) 108 { 109 no[++cou]=ed[i]; 110 no[cou].w=sum; 111 sum=0; 112 } 113 } 114 cdq(1,cou); 115 for(re i=1;i<=cou;i++) 116 cnt[no[i].ans+no[i].w-1]+=no[i].w; 117 for(re i=0;i<n;i++) 118 {write(cnt[i]); 119 putchar(' ');} 120 return 0; 121 }