Luo Gu [P5283] XOR [dumplings] [stack] Trie

Subject to the effect:

Topic links: https://www.luogu.org/problemnew/show/P5283
given a sequence found m m intervals [ l i , r i ] [l_i,r_i] Such that the maximum interval and the XOR.


Ideas:

Do it first prefix XOR, so the problem is converted to find m m of l , r l,r such that l   x o r   r \sum l \ xor\ r large as possible.
Notice a [ l ]   x o r   a [ r ] = a [ r ]   x o r   a [ l ] a[l]\ xor\ a[r]=a[r]\ xor\ a[l] , so that if the elected l , r l,r , then will choose again r , l r,l . So we can ask the number of times × 2 \times 2 , so that each two successive query is a set of the same ( l , r ) ( r , l ) (l,r)(r,l) . Divided by 2 final answer on the line.
We maintain a heap, will each i i corresponding a [ i ]   x o r   a [ j ] a[i]\ xor\ a[j] biggest j j thrown inside the reactor, each taken interrogation top of the stack, the next large a [ i ]   x o r   a [ j ] a[i]\ xor\ a[j] thrown into the heap.
for x x seeking y Y making a [ x ]   x o r   a [ y ] a[x]\ xor\ a[y] as the first k k large apparently can T r i e Trie maintenance. Each time the right to use to determine the value to the left and right subtrees.
So you can not use persistent T r i e Trie to the completion of this question. time complexity O ( n log n ) O(n\log n)


Code:

#include <queue>
#include <cstdio>
#include <string>
#include <iostream>
#define mp make_pair
using namespace std;
typedef long long ll;

const int N=500010,LG=35;
int n,m,tot=1,trie[N*LG][2],cnt[N],size[N*LG];
ll a[N],ans;
priority_queue<pair<ll,int> > q;

ll read()
{
    ll d=0;
    char ch=getchar();
    while (!isdigit(ch)) ch=getchar();
    while (isdigit(ch))
        d=(d<<3)+(d<<1)+(ll)ch-48LL,ch=getchar();
    return d;
}

void insert(ll x)
{
    int p=1;
    for (int i=LG;i>=0;i--)
    {
        int id=(x>>(ll)i)&1;
        if (!trie[p][id]) trie[p][id]=++tot;
        p=trie[p][id];
        size[p]++;
    }
}

ll find(ll x,int k)
{
    int p=1; 
    ll ans=0;
    for (int i=LG;i>=0;i--)
    {
        int id=(x>>(ll)i)&1;
        if (trie[p][id^1]&&size[trie[p][id^1]]>=k)
        {
            ans=(ans<<1)|1;
            p=trie[p][id^1];
        }
        else if (trie[p][id])
        {
            k-=size[trie[p][id^1]];
         	ans<<=1;
         	p=trie[p][id];
        }
    }
    return ans;
}

int main()
{
    scanf("%d%d",&n,&m);
    insert(0); cnt[0]=1;
    for (int i=1;i<=n;i++)
    {
        a[i]=read();
        a[i]^=a[i-1];
        insert(a[i]);
        cnt[i]=1;
    }
    for (int i=0;i<=n;i++)
        q.push(mp(find(a[i],1),i));
    m*=2;
    while (m--)
    {
    	if (!q.size()) break;
        ans+=q.top().first;
        int i=q.top().second;
        q.pop();
        cnt[i]++;
        if (cnt[i]<=n+1)
            q.push(mp(find(a[i],cnt[i]),i));
    }
    cout<<ans/2LL;
    return 0;
}

Guess you like

Origin blog.csdn.net/SSL_ZYC/article/details/94644518