URL : http://acm.hdu.edu.cn/showproblem.php?pid=6059
题意
Give you an array A[1..n],you need to calculate how many tuples (i,j,k) satisfy that (i< j< k) and ((A[i] xor A[j])<(A[j] xor A[k]))
题解
看了别人题解大半天,才终于明白,随便记下自己的理解
对于所有的 ((A[i] xor A[j])<(A[j] xor A[k]))
假设我们用字典树记录了A[1 ~ k-1],当前加入
Ak
字典树中以第30位为根,假设当前处理到了第 p 位
若
Ak[p]
代表
Ak
第 p 位的值,且
Ai、Ak
高位都是相同的
当
Ak[p]=1
时:
必然
Ai[p]=0、Aj[p]=0
时才有价值,下面考虑
Aj
的取值情况
1.
Aj
的高位与
Ak、Ak
都相同的情况 1LL * dat[Fson].num * (dat[Fson].num - 1) / 2;
2.
Aj
的高位与
Ak、Ak
不都都相同的情况 dat[Fson].num * (cnt[o][1-t] - dat[Fson].num) - dat[Fson].exn;
当 Ak[p]=0 时:同上讨论即可
注: 减去 dat[Fson].exn,dat[Fson].exn是 i > j 时 满足条件2 的情况
#include<stdio.h>
#include<string.h>
typedef long long LL;
const int MAXN = 2e5 + 5;
struct node {int num, exn, son[2]; } dat[31 * MAXN];
LL ans = 0;
int sz, cnt[31][2];
inline void cle(int x) {
dat[x].son[0] = dat[x].son[1] = dat[x].num = dat[x].exn = 0;
}
inline void add(int n, int o) {
int z = 0;
while(o >= 0) {
int t = n>>o&1;
int &Fson = dat[z].son[1-t];
int &Tson = dat[z].son[ t];
if(Fson) {
ans += 1LL * dat[Fson].num * (dat[Fson].num - 1) / 2;
ans += 1LL * dat[Fson].num * (cnt[o][1-t] - dat[Fson].num) - dat[Fson].exn;
}
if(Tson) {
z = Tson;
}
else {
z = Tson = ++sz;
cle(Tson);
}
++dat[z].num;
++cnt[o][t];
dat[z].exn += cnt[o][t] - dat[z].num; // all of j < i in this node
--o;
}
}
int main()
{
int T, n, x;
scanf("%d", &T);
while(T--) {
memset(cnt, 0, sizeof(cnt));
scanf("%d", &n);
ans = sz = 0;
cle(0);
while(n--) {
scanf("%d", &x);
add(x, 30);
}
printf("%lld\n", ans);
}
return 0;
}