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

    题面

    https://www.luogu.com.cn/problem/P5283

    大意是选择k个不同的连续区间,使区间异或和的总和最大

    分析

    求异或和,可以先对前缀异或和建一棵trie树

    固定端点在trie中找与之异或值最大的01串,将异或值和以该端点为右端点的异或值排名加入堆

    每次从堆中取出最大异或值并更新以该端点为右端点的区间异或值

    为了跳过对于该端点已经选择过的01串,要在trie上找到大小排名为排名+1的(类似线段树二分)01串加入堆

    注意细节

    代码

    #include <iostream> 
    #include <cstdio>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const ll Inf=1ll<<31;
    const int N=5e5+10;
    int t[32*N][2],cnt,sz[32*N];
    int n,k;
    ll s[N],lans;
    struct Pack {
        int id,times;
        ll val;
        friend bool operator < (Pack a,Pack b) {return a.val<b.val;}
    };
    priority_queue<Pack> q;
    
    void Insert(ll s) {
        int x=0;
        for (ll i=Inf;i;i>>=1) {
            bool wch=(s&i)>0;
            if (!t[x][wch]) t[x][wch]=++cnt;
            x=t[x][wch];sz[x]++;
        }
    }
    
    ll Get_Ans(ll s,int met) {
        int x=0;ll ans=0;
        for (ll i=Inf;i;i>>=1) {
            bool wch=(s&i)>0;
            if (met<=sz[t[x][wch^1]]) ans+=i,x=t[x][wch^1]; else met-=sz[t[x][wch^1]],x=t[x][wch];
        }
        return ans;
    }
    
    int main() {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]^=s[i-1],Insert(s[i]);Insert(0);
        for (int i=0;i<=n;i++) q.push((Pack){i,1,Get_Ans(s[i],1)});
        for (int i=1;i<=2*k;i++) {
            Pack temp=q.top();q.pop();
            lans+=temp.val;
            if (temp.times<n) q.push((Pack){temp.id,temp.times+1,Get_Ans(s[temp.id],temp.times+1)});
        }
        printf("%lld",lans/2ll);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    后台数据显示在网页(通过ajax获取内容)二
    获取后台数据显示在网页(一)
    访问后台方法
    input的placeholder字体大小无法修改?
    cssText()
    flex属性值----弹性盒子布局
    多栏布局
    怎么在ng-repeat生成的元素上操作dom
    css实现一行文字居中,多行文字左对齐
    变形属性 transform
  • 原文地址:https://www.cnblogs.com/mastervan/p/14543258.html
Copyright © 2011-2022 走看看