zoukankan      html  css  js  c++  java
  • 可持久化trie

    可持久化trie树

    https://www.luogu.org/problem/P4735

    题目描述

    给定一个非负整数序列{a},初始长度为N。

    有M个操作,有以下两种操作类型:

    1. A x:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。

    2. Q l r x:询问操作,你需要找到一个位置p,满足l≤p≤r,使得:a[p]⊕a[p+1]⊕...⊕a[N]⊕x最大,输出最大是多少。

      solution

      异或满足可减性,所以可以维护前缀和

      添加操作就方便了

      就是询问操作不太好处理

      // luogu-judger-enable-o2
      #include <bits/stdc++.h>
      using namespace std;
      #define maxn 600009
      int rt[maxn],cnt[maxn*28];
      int ch[maxn*28][2];
      int qz[maxn];
      int tt=1;
      int n,m;
      void ins(int a,int b,int t,int x) {
          if(t<0) return;
          int i=(x>>t)&1;
          ch[a][!i]=ch[b][!i];
          ch[a][i]=tt++;
          cnt[ch[a][i]]=cnt[ch[b][i]]+1;
          ins(ch[a][i],ch[b][i],t-1,x);
      }
      int qu(int a,int b,int t,int x) {
          if(t<0) return 0;
          int i=(x>>t)&1;
          if(cnt[ch[b][!i]]>cnt[ch[a][!i]]) {
              return (1<<t)+qu(ch[a][!i],ch[b][!i],t-1,x);
          }
          else {
              return qu(ch[a][i],ch[b][i],t-1,x);
          }
      }
      int main(){
          scanf("%d%d",&n,&m);
          int a,b,c,i,j;
          char s[5];
          rt[0]=tt++;
          ins(rt[0],0,25,0);
          for(a=1;a<=n;a++) {
              scanf("%d",&b);
              qz[a]=qz[a-1]^b;
              rt[a]=tt++;
              ins(rt[a],rt[a-1],25,qz[a]);
          }
          for(a=1;a<=m;a++) {
              scanf("%s",s);
              if(s[0]=='A') {
                  scanf("%d",&b);
                  n++;
                  qz[n]=qz[n-1]^b;
                  rt[n]=tt++;
                  ins(rt[n],rt[n-1],25,qz[n]);
              }
              else {
                  scanf("%d%d%d",&i,&j,&b);
                  i--;j--;
                  if(i==0) printf("%d
      ",qu(0,rt[j],25,b^qz[n]));
                  else printf("%d
      ",qu(rt[i-1],rt[j],25,b^qz[n]));
              }
          }
          return 0;
      }
      

    还有一种非递归版的:

    // luogu-judger-enable-o2
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int n,m,trie[20000000][2],root[20000000],size[20000000],node_cnt,node;
    inline int read()
    {
        int X(0),w(0);char ch(0);
        while (!isdigit(ch))w|=ch=='-',ch=getchar();
        while (isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    inline void write(int x)
    {
        if (x<0) putchar('-'),x=-x;
        if (x>9) write(x/10);
        putchar(x%10+'0');
    }
    int getc()
    {
        char ch=getchar();
        while(ch<'A'||ch>'Z')ch=getchar();
        return ch=='A';
    }
    void insert(int x)
    {	
        int rt=root[node_cnt];
        root[++node_cnt]=++node;
        for (register int i=24;i>=0;i--)
        {
            int ch=(x>>i)&1;
            size[node]=size[rt]+1;
            trie[node][ch]=node+1;
            trie[node][!ch]=trie[rt][!ch];
            rt=trie[rt][ch];
            node++;
        }
        size[node]=size[rt]+1;
    }
    void query(int l,int r,int x)
    {
        int lc=root[l],rc=root[r],ans=0;
        for (register int i=24;i>=0;i--)
        {
            int ch=(x>>i)&1;
            if (size[trie[rc][!ch]]-size[trie[lc][!ch]]>0)
                lc=trie[lc][!ch],rc=trie[rc][!ch],ans|=1<<i;
            else
                lc=trie[lc][ch],rc=trie[rc][ch];
        }
        write(ans);
        putchar(10);
    }
    int main()
    {
        n=read();m=read();
        int x,sum=0;
        insert(0);
        for (register int i=1;i<=n;i++)
            x=read(),sum^=x,insert(sum);
        int l,r,z,ch;
        for (register int i=1;i<=m;i++)
        {
            ch=getc();
            if (ch==1)
                z=read(),sum^=z,insert(sum);
            else
                l=read(),r=read(),z=read(),query(l-1,r,z^sum);
        }
        return 0;
    }
    
  • 相关阅读:
    Java-判断一个数是不是素数
    Sublime快捷键
    python
    全排列
    python
    python
    OpenCV 实现图像结构相似度算法 (SSIM 算法)
    C++
    C++
    NFA 转 DFA
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11605265.html
Copyright © 2011-2022 走看看