首页 > 其他 > 详细

可持久化trie(带修改最大异或和BZOJ 3261)

时间:2019-07-22 20:14:27      阅读:98      评论:0      收藏:0      [点我收藏+]

感觉可持久化trie最多就是用在异或和上了吧。

技术分享图片
#include<bits/stdc++.h>
#define N 
#define INF 2100000001
using namespace std;
int read()
{
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
} 
int go[600005*23][3],root[600005],latest[600005*23],a[600005];
int tot=0;
void insert(int i,int k,int p,int q)
{
    if(k<0){latest[q]=i;return;}
    int c=a[i]>>k&1;
    if(p)go[q][c^1]=go[p][c^1];//除了字符指针si不同之外,节点q和节点p的其他信息完全相同 
    go[q][c]=++tot;
    insert(i,k-1,go[p][c],go[q][c]);
    latest[q]=max(latest[go[q][0]],latest[go[q][1]]);//latest表示在可持久化trie中以q为根的子树中结尾标记的最大(最晚的可以到达此点的trie)
    //满足大于l-1就行了 
} 
int query(int q,int val,int k,int lim)
{
    if(k<0) return a[latest[q]]^val;
    int c=val>>k&1;
    if(latest[go[q][c^1]]>=lim)return query(go[q][c^1],val,k-1,lim);
    else return query(go[q][c],val,k-1,lim);
}
char op[2];
int main()
{
    int n=read(),m=read();
    latest[0]=-1;
    for(int i=1;i<=n;++i)
    {
        a[i]=read();
        a[i]=a[i]^a[i-1];//存前缀和 
        root[i]=++tot;
        insert(i,23,root[i-1],root[i]);//不会超过2^23 
    }
    for(int i=1;i<=m;++i)
    {
        scanf("%s",&op);
        if(op[0]==A)
        {
            int x=read();
            ++n;
            a[n]=x;
            a[n]=a[n]^a[n-1];
            root[n]=++tot;
            insert(n,23,root[n-1],root[n]);
        }
        else
        {
            int l=read(),r=read(),x=read();
            printf("%d\n",query(root[r-1],a[n]^x,23,l-1));//r-1和l-1,因为要消去前面的前缀异或和(a^a=0) 
        }
    }
} 
View Code

 

可持久化trie(带修改最大异或和BZOJ 3261)

原文:https://www.cnblogs.com/yyys-/p/11228066.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!