【模板】三维偏序(陌上花开)
作者:互联网
[模板] 三维偏序(陌上花开)
Solution:
CDQ分治求解三维偏序。
1、首先三关键字排序,保证接下来\(i\)的可行解一定在\([1,i-1]\)中。
2、再对第二关键字做归并排序,保证满足\(a_j<a_i\)的前提下,实现\(b_j<b_i\)。合并时有两个区间,\(j<i\),\(j\)在\([l,mid]\)中,\(i\)在\([mid+1,r]\)中,由于前一次对三关键字的排序,使得左区间所有\(a\)小于等于右区间所有\(a\),所以在归并维护答案时,无需顾忌\(a\)的情况,靠双指针来保证\(b\)有序,然后同时统计\(c\)的答案即可。
3、归并时双指针与树状数组维护第三关键字对答案的贡献,注意重复三维点的情况。
Code:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
inline int read() {
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
return x*f;
}
inline void out(int x) {
if(x>9) out(x/10);
putchar(x%10+'0');
}
int n,k;
struct node{
int a,b,c;
int cnt;
int sum;
void print(){
cout<<"a="<<a<<" b="<<b<<" c="<<c<<" cnt="<<cnt<<" sum="<<sum<<endl;
}
bool operator < (const node &t)const{
if(t.a!=a)return a<t.a;
if(t.b!=b)return b<t.b;
return c<t.c;
}
bool operator == (const node &t)const{
return t.a==a&&t.b==b&&t.c==c;
}
node():a(0),b(0),c(0),cnt(0),sum(0){}
node(int _a,int _b,int _c,int _cnt,int _sum):a(_a),b(_b),c(_c),cnt(_cnt),sum(_sum){}
}q[N],w[N],kep[N];
int ans[N];
#define lowbit(x) (x&(-x))
int c[N];
void add(int pos,int val){
while(pos<N){
c[pos]+=val;
pos+=lowbit(pos);
}
}
int geta(int pos){
int ans=0;
while(pos){
ans+=c[pos];
pos-=lowbit(pos);
}
return ans;
}
void merge_sort(int l,int r){
if(l==r)return ;
int mid = (l+r)>>1;
merge_sort(l,mid),merge_sort(mid+1,r);
int i=l,j=mid+1;
int k=0;
while(i<=mid&&j<=r){
if(q[i].b<=q[j].b)add(q[i].c,q[i].cnt),w[k++]=q[i++];
else q[j].sum+=geta(q[j].c),w[k++]=q[j++];
}
while(i<=mid)add(q[i].c,q[i].cnt),w[k++]=q[i++];
while(j<=r)q[j].sum+=geta(q[j].c),w[k++]=q[j++];
for(int o=l;o<=mid;++o)add(q[o].c,-q[o].cnt);
for(int i=0,st=l;i<k;++i){
q[st+i] = w[i];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>k;
rep(i,1,n){
int x,y,z;
cin>>x>>y>>z;
q[i]=node(x,y,z,1,0);
}
sort(q+1,q+1+n);
int siz=0;
for(int i=1;i<=n;++i){
int pos = i;
int cnt = 0;
while(pos<=n&&q[pos]==q[i]){
pos++;
cnt++;
}
kep[++siz] = q[i];
kep[siz].cnt = cnt;
i=pos-1;
}
for(int i=1;i<=siz;++i){
q[i] = kep[i];
}
merge_sort(1,siz);
for(int i=1;i<=siz;++i){
ans[q[i].cnt-1+q[i].sum]+=q[i].cnt;
}
for(int i=0;i<n;++i){
cout<<ans[i]<<"\n";
}
return 0;
}
标签:偏序,sort,int,陌上,mid,long,while,模板 来源: https://www.cnblogs.com/quuns/p/15043107.html