zoukankan      html  css  js  c++  java
  • hdu6059 Kanade's trio 字典树+容斥

    转自:http://blog.csdn.net/dormousenone/article/details/76570172
    /**
    题目:hdu6059 Kanade's trio
    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6059
    题意:含 N 个数字的 A 数组,求有多少个三元组 (i,j,k) 满足 i<j<k 且 (Ai⊕Aj)<(Aj⊕Ak)
    思路:
    利用字典树维护前 k-1 个数。当前处理第 k 个数。
    
    显然对于 k 与 i 的最高不相同位 kp 与 ip :
    
    当 ip=0 , kp=1 时,该最高不相同位之前的 ihigher=khigher 。则 jhigher 可以为任意数,
    
    均不对 i, k 更高位(指最高不相同位之前的高位,后同)的比较产生影响。而此时 jp 位必须为 0 才可保证不等式 (Ai⊕Aj)<(Aj⊕Ak) 成立。
    
    当 ip=1,kp=0 时,jp 位必须为 1 ,更高位任意。
    
    故利用数组 cnt[31][2] 统计每一位为 0 ,为 1 的有多少个(在前 K-1 个数中)。
    
    在字典树插入第 k 个数时,同时统计最高不相同位,即对于每次插入的 p 位为 num[p] (取值 0 或 1),
    
    在同父节点对应的 1-num[p] 为根子树的所有节点均可作为 i 来寻找 j 以获取对答案的贡献。
    
    其中又仅要求 jp 与 ip (ip 值即 1-num[p]) 相同,故 jp 有 cnt[p][ 1-num[p] ] 种取值方案。
    
    但是,同时需要注意 i 与 j 有在 A 数组的先后关系 (i<j) 需要保证。
    
    故在字典树中额外维护一个 Ext 点,记录将每次新加入的点与多少原有点可构成 i, j 关系。在后续计算贡献时去掉。
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const int maxnode = 5e5*30+10;
    const int maxn = 5e5+100;
    const int sigma_size = 2;
    int cnt[maxn][30];
    int ch[maxnode][sigma_size];
    int sz;
    int idx(char c){return c-'a';}
    LL ans, ext;
    struct node
    {
        int cnt;
        int ext;
    }val[maxnode];
    int s[30];
    void insert()
    {
        int u = 0;
        for(int i = 29; i >= 0; i--){
            int c = s[i];
            if(ch[u][!c]){
                ans += (LL)val[ch[u][!c]].cnt*(val[ch[u][!c]].cnt-1)/2;
                ext += (LL)val[ch[u][!c]].cnt*(cnt[i][!c]-val[ch[u][!c]].cnt)-val[ch[u][!c]].ext;
            }
            if(!ch[u][c]){
                memset(ch[sz], 0, sizeof ch[sz]);
                val[sz].cnt = 0;
                val[sz].ext = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
            val[u].cnt++;
            val[u].ext += cnt[i][c]-val[u].cnt;
        }
    }
    int main()
    {
        //freopen("C:\Users\accqx\Desktop\in.txt","r",stdin);
        int T, n;
        cin>>T;
        while(T--)
        {
            scanf("%d",&n);
            int x;
            sz = 1;
            memset(ch[0], 0, sizeof ch[0]);
            memset(cnt, 0, sizeof cnt);
            ans = ext = 0;
            for(int i = 1; i <= n; i++){
                scanf("%d",&x);
                for(int j = 0; j < 30; j++){
                    cnt[j][x%2]++;
                    s[j] = x%2;
                    x/=2;
                }
                insert();
            }
            printf("%lld
    ",ans+ext);
        }
    
        return 0;
    }
  • 相关阅读:
    SAP S/4HANA extensibility扩展原理介绍
    SAP CRM系统订单模型的设计与实现
    使用nodejs代码在SAP C4C里创建Individual customer
    SAP Cloud for Customer Account和individual customer的区别
    Let the Balloon Rise map一个数组
    How Many Tables 简单并查集
    Heap Operations 优先队列
    Arpa’s obvious problem and Mehrdad’s terrible solution 思维
    Passing the Message 单调栈两次
    The Suspects 并查集
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7286945.html
Copyright © 2011-2022 走看看