HDU 6059 Kanade's trio

http://acm.hdu.edu.cn/showproblem.php?pid=6059

http://blog.csdn.net/dpppbr/article/details/76565715
一開始並不會做,完全沒頭緒。看了這位dalao的博客纔會的。感覺我就是把這位dalao的代碼扒了下來…………慚愧…………
哇,題意就是 給你n個數,找出這n個數中多少組(i,j,k) i

#include <bits/stdc++.h>
#define maxs 2002020
#define mme(i,j) memset(i,j,sizeof(i))
using namespace std;
int a[maxs];
int nex[maxs][3],sum[maxs],cnt[33][3],val[maxs];
int tot,root;

int newnode()
{
    mme(nex[tot],-1);
    sum[tot]=val[tot]=0;
    return tot++;
}

void init()
{
    tot=0;
    root-newnode();
    mme(cnt,0);
    return;
}

void Insert(int x,int v)
{
    int id,now=root;
    for(int i=30;i>=0;i--)
    {
        id = ((x>>i)&1);

        if( nex[now][id] == -1 ) nex[now][id] = newnode();
        now = nex[now][id];
        cnt[i][id]++;//第i位0/1 出現了幾次
        sum[now] += v*cnt[i][id^1];// 每個狀態對答案產生了多少貢獻
        val[now] += v;//每個狀態出現的次數
    }
}

long long get(int x)
{
    long long ans=0;
    int tp,id,now=root;

    for(int i=30;i>=0;i--){

        id = ( (x>>i)&1 );

        tp=nex[now][id^1];
        now=nex[now][id];
        if(tp!=-1) ans+= sum[tp] - val[tp]*cnt[i][id];//當前狀態產生的貢獻- 當前狀態出現的次數*當前位相反數值出現的次數。
        if(now==-1) break;

    }
    return ans;
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++) {scanf("%d",&a[i]);Insert(a[i],1); }
        long long ans=0;
        mme(cnt,0);
        for(int i=1;i<n;i++)
        {
            Insert(a[i],-1);
            ans+=get(a[i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章