zoukankan      html  css  js  c++  java
  • [十二省联考2019] 异或粽子

    (n) 元数列的 (k) 个不同的子区间使得各个子区间异或和之和最大。

    Solution

    (差点又看错题了)

    做个前缀和,于是转化成求序列异或和最大的 (k) 个数对

    建一棵可持久化 0-1 Trie,这样我们就可以 (O(log n)) 求出对于某个右端点,它的所有可能答案中,第 (k) 大的答案

    然后利用堆来维护答案。我们先把对每一个右端点,第 (1) 大的答案插入堆。然后循环弹出。每次弹出一个,如果它是 (u) 这个右端点对应的第 (v) 大的答案,我们就计算出 (u) 这个右端点对应的第 (v+1) 大的答案(如果存在的话)并且把它插入堆,然后继续。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1000005;
    
    namespace trie {
        int ind,ch[N*40][2],siz[N*40],root[N*40];
        void insert(int id,int x) {
            root[id]=++ind;
            ch[ind][0]=ch[root[id-1]][0];
            ch[ind][1]=ch[root[id-1]][1];
            siz[ind]=siz[root[id-1]]+1;
            int p=ind;
            for(int i=39;i>=0;--i) {
                int t=(x>>i)&1;
                ++ind;
                ch[ind][0]=ch[ch[p][t]][0];
                ch[ind][1]=ch[ch[p][t]][1];
                siz[ind]=siz[ch[p][t]]+1;
                ch[p][t]=ind;
                p=ind;
            }
        }
        int query(int id,int x,int k) {
            int p=root[id],ans=0;
            for(int i=39;i>=0;--i) {
                int t=(x>>i)&1;
                if(siz[ch[p][t^1]]>=k) {
                    p=ch[p][t^1];
                    ans|=1ll<<i;
                }
                else {
                    k-=siz[ch[p][t^1]];
                    p=ch[p][t];
                }
            }
            return ans;
        }
    }
    
    struct pii {
        int a,b,c;
        bool operator < (const pii &x) const {
            return a < x.a;
        }
    };
    
    priority_queue <pii> q;
    int n,k,a[N],ans;
    
    signed main() {
        scanf("%lld%lld",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%lld",&a[i]);
            a[i]^=a[i-1];
        }
        for(int i=0;i<=n;i++) {
            trie::insert(i,a[i]);
        }
        for(int i=1;i<=n;i++) {
            q.push((pii){trie::query(i-1,a[i],1),i,1});
            //cout<<trie::query(i-1,a[i],1)<<" ";
        }
        //cout<<endl;
        for(int i=1;i<=k;i++) {
            int val=q.top().a,pos=q.top().b,idx=q.top().c;
            ans+=val;
            //cout<<val<<endl;
            q.pop();
            if(idx<pos) {
                q.push((pii){trie::query(pos-1,a[pos],idx+1),pos,idx+1});
            }
        }
        cout<<ans;
    }
    
  • 相关阅读:
    Hashset;HashMap;ArrayList;
    排序方法(冒泡排序,直接选择排序,反转排序);
    父类引用指向子类的对象;
    SQL分支语句与循环语句
    ORCAL 数据库的约束以及SQL语言的四种类型
    Oracle基础数据类型与运算符
    集合
    数组的几种排序
    转换日期格式的工具类
    equals方法重写
  • 原文地址:https://www.cnblogs.com/mollnn/p/12295392.html
Copyright © 2011-2022 走看看