• 十二省联考2019 异或粽子


    题目链接:戳我

    其实和超级钢琴那个题思路挺像的,就是我们弄一个二元组,一个pos,一个sum。

    超级钢琴那个题的主席树思路大家可以借鉴一下,这里也就是换成了可持久化01trie。

    求一下前缀异或和,然后在它pos前面的01trie里面查询第k大即可。

    代码如下:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define MAXN 500010
    using namespace std;
    int n,k,root=1,tot=1;
    int a[MAXN],ch[MAXN*50][2],cnt[MAXN*50],rt[MAXN];
    long long ans;
    long long sum[MAXN];
    struct Node{
        int pos,cnt;
        long long maxx;
        friend bool operator < (struct Node x,struct Node y)
            {return x.maxx<y.maxx;}
    };
    priority_queue<Node>q;
    inline void build()
    {
        int now=1;
        rt[0]=1;
        for(int i=31;i>=0;i--)
        {
            ch[now][0]=++tot;
            cnt[ch[now][0]]=1;
            now=ch[now][0];
        }
    }
    inline void init(int &x,int f,long long sum,int kkk)
    {
        x=++tot;
        cnt[x]=cnt[f]+1;
        ch[x][0]=ch[f][0],ch[x][1]=ch[f][1];
        if(kkk<0) return;
        int v=((sum>>kkk)&1);
        if(!v) init(ch[x][0],ch[f][0],sum,kkk-1);
        else init(ch[x][1],ch[f][1],sum,kkk-1);
    }
    
    inline long long query(int x,long long ss,int k)
    {
        long long cur_ans=0;
        for(int i=31;i>=0;i--)
        {
            int v=((ss>>i)&1);
            if(!v)
            {
                if(k<=cnt[ch[x][1]]) x=ch[x][1],cur_ans=(cur_ans<<1)|1;
                else k-=cnt[ch[x][1]],x=ch[x][0],cur_ans=(cur_ans<<1);
            }
            else
            {
                if(k<=cnt[ch[x][0]]) x=ch[x][0],cur_ans=(cur_ans<<1)|1;
                else k-=cnt[ch[x][0]],x=ch[x][1],cur_ans=(cur_ans<<1);
            }
        }
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        build();
        for(int i=1;i<=n;i++)
        {
            sum[i]=sum[i-1]^a[i];
            //printf("sum[%d]=%lld
    ",i,sum[i]);
            Node cur;
            cur.cnt=1;
            cur.maxx=query(rt[i-1],sum[i],1);
            cur.pos=i;
            q.push(cur);
            //printf("%d %d %d
    ",cur.pos,cur.maxx,cur.cnt);
            init(rt[i],rt[i-1],sum[i],31);
        }
        for(int i=1;i<=k;i++)
        {
            Node cur=q.top();q.pop();
            ans+=cur.maxx;
            if(cur.cnt>=cur.pos) continue;
            cur.cnt++;
            cur.maxx=query(rt[cur.pos-1],sum[cur.pos],cur.cnt);
            q.push(cur);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    Linux标准C头文件和内核头文件的理解
    linux GCC编译C程序的问题
    C#类型反射、晚期绑定、特性编程的使用背景与分析
    linux下C#开发mongoDB
    C中“指针和数组”引发的探索一
    C#学习记录
    linux下Apache+PHP+mysql+phpMyAdmin源码包安装配置
    基于mongoDB和C#分布式海量文件存储实验
    C中指针和数组引发的探索二
    算法研究学习一(用C和C#实现)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10675541.html
Copyright © 2020-2023  润新知