【题目描述】
给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数。
【输入格式】
第一行一个整数n,表示序列长度。
第二行n个整数,分别表示a1~an。
第三行n个整数,分别表示b1~bn。
第四行n个整数,分别表示c1~cn。
【输出格式】
一个整数,表示答案。
【样例输入】
5 1 5 3 4 2 2 5 3 4 1 1 2 5 3 4
【样例输出】
3
【样例解释】
满足条件的(i,j)共有以下三对:
(1,2)
(1,3)
(1,4)
【数据范围与约定】
对于30%的数据,n<=5000。
对于100%的数据,1<=n<=50000,保证所有的ai、bi、ci分别组成三个1~n的排列。
【来源】
HZOI 2016
练习一下CDQ分治,写了一个CDQ套CDQ。突然发现CDQ真的太好写了,别说4维了,6、7维偏序都不是问题(虽然可能还卡不过n^2)。
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn = 1e5 + 5;
struct node {
int id, a, b, c;
}t[maxn];
int n;
LL ans;
bool cmp_abc(const node &A, const node &B) {
return A.a == B.a ? A.b == B.b ? A.c == B.c ? A.id < B.id : A.c < B.c : A.b < B.b : A.a < B.a;
}
bool cmp_bca(const node &A, const node &B) {
return A.b == B.b ? A.c == B.c ? A.a == B.a ? A.id < B.id : A.a < B.a : A.c < B.c : A.b < B.b;
}
bool cmp_cab(const node &A, const node &B) {
return A.c == B.c ? A.a == B.a ? A.b == B.b ? A.id < B.id : A.b < B.b : A.a < B.a : A.c < B.c;
}
namespace BIT {
int tree[maxn];
#define lowbit(x) ((x) & (-(x)))
void add(int x, int dt) {
for(register int i = x; i <= n; i += lowbit(i))
tree[i] += dt;
}
int query(int x) {
int ans = 0;
for(register int i = x; i; i -= lowbit(i))
ans += tree[i];
return ans;
}
}
void cdq(int l, int r, int m1) {
if(l == r) return ;
int mid = l + r >> 1, tmp = t[mid].a;
cdq(l, mid, m1), cdq(mid + 1, r, m1);
sort(t + l, t + r + 1, cmp_bca);
for(register int i = l; i <= r; ++i) {
if(t[i].a <= tmp && t[i].id <= m1)
BIT::add(t[i].c, 1);
if(t[i].a > tmp && t[i].id > m1)
ans += BIT::query(t[i].c - 1);
}
for(register int i = l; i <= r; ++i)
if(t[i].a <= tmp && t[i].id <= m1) BIT::add(t[i].c, -1);
}
void CDQ(int l, int r) {
if(l == r) return ;
int mid = l + r >> 1;
CDQ(l, mid), CDQ(mid + 1, r);
sort(t + l, t + r + 1, cmp_abc);
cdq(l, r, mid);
}
int main() {
freopen("partial_order.in", "r", stdin);
freopen("partial_order.out", "w", stdout);
scanf("%d", &n);
for(register int i = 1; i <= n; ++i)
scanf("%d", &t[i].a);
for(register int i = 1; i <= n; ++i)
scanf("%d", &t[i].b);
for(register int i = 1; i <= n; ++i)
scanf("%d", &t[i].c), t[i].id = i;
CDQ(1, n);
printf("%lld", ans);
return 0;
}
rockdu
没有帐号? 立即注册