hdu 6059 Kanade's trio(字典树)

Kanade's trio

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


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
1
5
1 2 3 4 5
 
Sample Output
6

 

Source
Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6119  6118  6117  6116  6115 
 

题解:http://blog.csdn.net/dormousenone/article/details/76570172

这题:一直wa,把 tree[] 数组中的int改 long long 就错了,诶找了半天错误

#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;

struct node
{
    int cnt,ext;
    int nxt[2];
}tree[500010*31];
int a[500000+10],num[30],cnt[31][2];
long long ans,ext;
int T,n,tsize;

void cal(int k,long long c)
{
    ans+=(tree[k].cnt-1)*tree[k].cnt/2;
    ext+=tree[k].cnt*(c-tree[k].cnt)-tree[k].ext;
}


void solve()
{
    int tmp=0;
    for(int i=0;i<=29;i++)
    {
        if (!tree[tmp].nxt[num[i]]) 
            tree[tmp].nxt[num[i]]=++tsize;
        if (tree[tmp].nxt[1-num[i]])
           cal(tree[tmp].nxt[1-num[i]],cnt[i][1-num[i]]);
        tmp=tree[tmp].nxt[num[i]];
        tree[tmp].cnt++;
        tree[tmp].ext+=cnt[i][num[i]]-tree[tmp].cnt;
    }
    return;
}


int main()
{
    scanf("%d",&T);
    for(;T>0;T--)
    {
        scanf("%d",&n);
        memset(cnt,0,sizeof(cnt));
        memset(tree,0,tsize*16+16);
        tsize=0;
        ans=ext=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            int tmp=a[i];
            for(int j=29;j>=0;j--)
            {
                cnt[j][tmp%2]++;
                num[j]=tmp%2;
                tmp/=2;
            }
           solve();
        }
        printf("%lld\n",ans+ext);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/stepping/p/7357501.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值