[COGS2479]偏序
[COGS2479]偏序
题目大意:
\(n(n\le50000)\)个四元组,求四维偏序。
思路:
CDQ分治套CDQ分治套树状数组。
细节:
第二层CDQ之前要备份数组\(a\),否则第二层CDQ结束以后\(a\)就不对了。
源代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=50001;
int n,ans;
struct Node {
int id,x,y,z,type;
};
Node a[N],tmp[N];
inline bool cmp1(const Node &p1,const Node &p2) {
return p1.x<p2.x;
}
inline bool cmp2(const Node &p1,const Node &p2) {
return p1.y<p2.y;
}
class FenwickTree {
private:
int val[N];
int lowbit(const int &x) const {
return x&-x;
}
public:
void modify(int p,const int &x) {
for(;p<=n;p+=lowbit(p)) val[p]+=x;
}
int query(int p) const {
int ret=0;
for(;p;p-=lowbit(p)) ret+=val[p];
return ret;
}
};
FenwickTree t;
void cdq2(const int &b,const int &e) {
if(b==e) return;
const int mid=(b+e)>>1;
cdq2(b,mid);
cdq2(mid+1,e);
int p=b,q=mid+1;
for(;q<=e;q++) {
if(a[q].type==1) continue;
for(;p<=mid&&a[p].y<a[q].y;p++) {
if(a[p].type==1) t.modify(a[p].z,1);
}
ans+=t.query(a[q].z);
}
while(--p>=b) {
if(a[p].type==1) t.modify(a[p].z,-1);
}
std::inplace_merge(&a[b],&a[mid]+1,&a[e]+1,cmp2);
}
void cdq1(const int &b,const int &e) {
if(b==e) return;
const int mid=(b+e)>>1;
cdq1(b,mid);
cdq1(mid+1,e);
for(register int i=b;i<=mid;i++) a[i].type=1;
for(register int i=mid+1;i<=e;i++) a[i].type=2;
std::inplace_merge(&a[b],&a[mid]+1,&a[e]+1,cmp1);
std::copy(&a[b],&a[e]+1,&tmp[b]);
cdq2(b,e);
std::copy(&tmp[b],&tmp[e]+1,&a[b]);
}
int main() {
freopen("partial_order.in","r",stdin);
freopen("partial_order.out","w",stdout);
n=getint();
for(register int i=1;i<=n;i++) a[i].id=i;
for(register int i=1;i<=n;i++) a[i].x=getint();
for(register int i=1;i<=n;i++) a[i].y=getint();
for(register int i=1;i<=n;i++) a[i].z=getint();
cdq1(1,n);
printf("%d\n",ans);
return 0;
}