Luogu P5283 / LOJ3048 【[十二省聯考2019]異或粽子】


聯考Day1T1...一個考場上蠢了只想到\(O(n^2)\)復雜度的數據結構題

題目大意:

求前\(k\)大區間異或和的和

題目思路:

真的就是個sb數據結構題,可持久化01Trie能過(開O2)。

對於區間異或和,顯然可以處理成兩個前綴異或和的異或和,然后做法就非常蠢,把所有前綴異或和插入到可持久化01Trie里面,然后求以每個位置為右端點的最大區間前綴和,放入大根堆維護。然后從堆中取\(k\)次最大,每次取完把對應位置的相對當前的次大插入堆中。復雜度\(O(開O2能過)\)qwq。眾所周知01Trie非常短而且好寫不容易錯,剛寫了一遍直接就過了(忽略沒開O2被卡一個點的那次提交)。

當時真是蠢了,沒想到用01Trie真的是sb。

#include<bits/stdc++.h>

using namespace std;

const int N=5e5+5;

int n,k,rt[N],ch[N*40][2],cnt[N*40],cntnode,kth[N];

long long a[N],sum[N],ans;

struct node{
    long long val;int id;
    node(long long rv=0,int ri=0){
        val=rv;id=ri;
    }
    bool operator<(const node&rhs)const{
        return val<rhs.val;
    }
};

priority_queue<node>pq;

void insert(int lr,int &u,long long v,int dep){
    u=++cntnode;
    ch[u][0]=ch[lr][0];ch[u][1]=ch[lr][1];cnt[u]=cnt[lr];
    ++cnt[u];
    if(~dep){
        int now=(v>>dep)&1;
        insert(ch[lr][now],ch[u][now],v,dep-1);
    }
}

long long query(int u,long long v,int rk){
    long long rep=0;int now;
    for(int i=31;~i;i--){
        now=(v>>i)&1;
        if(cnt[ch[u][now^1]]<rk){
            rk-=cnt[ch[u][now^1]];
            u=ch[u][now];
        }
        else{
            rep|=(1LL<<i);
            u=ch[u][now^1];
        }
    }
    return rep;
}

int main(){
    scanf("%d%d",&n,&k);
    insert(0,rt[0],0,31);
    for(int i=1;i<=n;i++){
        kth[i]=1;
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]^a[i];
        insert(rt[i-1],rt[i],sum[i],31);
        pq.push(node(query(rt[i-1],sum[i],kth[i]),i));
    }
    while(k--){
        node u=pq.top();pq.pop();
        ++kth[u.id];
        ans+=u.val;
        pq.push(node(query(rt[u.id-1],sum[u.id],kth[u.id]),u.id));
    }
    printf("%lld\n",ans);
    return 0;
} 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM