HDU6059 Kanade's trio(异或字典树)

来源:互联网 发布:金蝶软件购买 编辑:程序博客网 时间:2024/06/07 01:15

Kanade's trio

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1067    Accepted Submission(s): 392


Problem Description
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]))

There are T test cases.

1T20

1n5105

0A[i]<230
 

Input
There is only one integer T on first line.

For each test case , the first line consists of one integer n ,and the second line consists of n integers which means the array A[1..n]
 

Output
For each test case , output an integer , which means the answer.
 

Sample Input
151 2 3 4 5
 

Sample Output
6
 

Source
2017 Multi-University Training Contest - Team 3 
 

Recommend
liuyiding
 



http://blog.csdn.net/DorMOUSENone/article/details/76570172?locationNum=2&fps=1 看的是这位大佬的博客学的。

题意:给一个数列,找出多少个这样的有序三元组<i,j,k>满足a[i] xor a[j] < a[j] xor a[k]



#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int N = 500000 + 10;const int Node_max = N * 31;int T, n, num[30], a[N], cnt[31][2];long long ext = 0, ans;struct Node{    int nxt[2];    int cnt, ext;} Trie[Node_max];int Tsize;void calc(int tmp, long long c) {    //当前节点往下走有多少个字符串,从中间选两个    ans += Trie[tmp].cnt * 1ll * (Trie[tmp].cnt - 1) / 2;    //c代表的是这一位上,和初始字符不用的字符个数    ext += (c-Trie[tmp].cnt) * 1ll * Trie[tmp].cnt - Trie[tmp].ext;}void Trie_insert(int idx){    int tmp = 0;    for(int i=0;i<30;i++){                if(!Trie[tmp].nxt[ num[i] ]) {            Trie[tmp].nxt[ num[i] ] = ++Tsize;        }        //如果另一条路能走        if(Trie[tmp].nxt[ 1-num[i] ]) {            calc(Trie[tmp].nxt[ 1-num[i] ], cnt[i][ 1-num[i] ]);        }        tmp = Trie[tmp].nxt[ num[i] ];        Trie[tmp].cnt++;        //        Trie[tmp].ext += cnt[i][num[i]] - Trie[tmp].cnt;    }    return;}int main(){    scanf("%d", &T);    while(T-- && scanf("%d", &n)!=EOF)    {        memset(Trie, 0, Tsize * 16 + 16);        memset(cnt, 0, sizeof(cnt));        Tsize = 0;        ans = 0;        ext = 0;        for(int i=1, tmp;i<=n;i++)        {            scanf("%d", &a[i]);            tmp = a[i];            for(int j=29;j>=0;j--) {                num[j] = tmp%2;                cnt[j][tmp%2]++;//记录每一位为0或者为1的有多少个                tmp /= 2;            }            Trie_insert(i);        }        printf("%lld\n", ans + ext);    }}




原创粉丝点击