2017第三次多校联合HDU6059

来源:互联网 发布:百度地图js api离线 编辑:程序博客网 时间:2024/06/05 17:03

题目

看了无数人的博客,冥思苦想终于搞明白了,都是泪啊。
题意:给你一个序列a,然后让你计算有多少个三元组(i,j,
k),满足i<j<k且((A[i] xor A[j])<(A[j] xor A[k]))。

题解:字典树。
用字典树处理前k-1个数,当前是第k个数。

显然,我们要寻找的i,j需要满足的条件可以转化为:AiAk的最高不同位t,而Aj的第t位与Ai的第t位相同。这样异或的结果就满足了要求。因为AiAk第t位之前的一定是全部相同的,所以不论Aj选取什么数,都不会对更高位的比较有影响。
举个例子:当it=0,kt=1,此时jt必须满足等于0,才能使异或结果满足条件,并且j的更高位是无所谓的。
所以利用数组cnt[31][2]记录已插入的数字中每一位的0/1有多少个,num数组表示第K个数的每一位。在插入第K个数的时候,统计最高不同位,插入的第t位是num[t],且他就是最高不同位,那它的同父节点的1num[t]为根节点的树中所有节点均可成为i来寻找j,假设这个1num[t]位根节点的树中有3个数字,就可以利用C(23)来进行选择(因为这三个数里一定有插入的先后顺序的,只要让小的成为i,大的成为j即可)。
但是对于插入的第t位来说,j不一定只在它的同父节点的子树里,因为j只需满足jtit相同即可,所以它可以在第t位所在的这一层中与it相同的子树中就可以。但是其中也会有不合法的情况,因为i是必须小于j的,所以我们添加ext这个变量来记录不合法的情况。
对于ext这个变量,我们在处理完一个点的时候,我们可以将这个点作为i,来寻找有多少个点可以与这个点形成i,j的关系,记录下来,最后一起减去。(因为我们插入的是第K个数,所以它一定是大于所有已经插入的数的,所以这里找到的情况都是不合法的)。
我就卡在这个ext这里卡了好久。。。难过。。。。

#include<bits/stdc++.h>using namespace std;#define ll long longconst int maxn=5e5+10;int cnt[31][2],a[maxn],num[30];struct bbq{    int nxt[2];    int cnt,ext;//cnt记录这个点被经过了几次。};bbq T[maxn*31];int tsize;long long ans;void calc(int tmp,int cnt){    ans+=T[tmp].cnt*1ll*(T[tmp].cnt-1)/2;    ans+=(cnt-T[tmp].cnt)*1ll*T[tmp].cnt-T[tmp].ext;}void in(){    int tmp=0;    for(int i=0;i<30;i++)    {        if(!T[tmp].nxt[num[i]])            T[tmp].nxt[num[i]]=++tsize;        if(T[tmp].nxt[1-num[i]])        {            calc(T[tmp].nxt[1-num[i]],cnt[i][1-num[i]]);        }        tmp=T[tmp].nxt[num[i]];        T[tmp].cnt++;        T[tmp].ext+=cnt[i][num[i]]-T[tmp].cnt;    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        scanf("%d",&n);        memset(num,0,sizeof num);        memset(cnt,0,sizeof cnt);        memset(T,0,sizeof T);        ans=tsize=0;        for(int i=0;i<n;i++)        {            scanf("%d",&a[i]);            int temp=a[i];            for(int j=29;j>=0;j--)            {                num[j]=temp%2;                cnt[j][temp%2]++;                temp/=2;            }            in();        }        printf("%lld\n",ans);    }}
原创粉丝点击