zoukankan      html  css  js  c++  java
  • 洛谷P4735题解

    若想要深入学习可持久化0-1Trie树,传送门


    Description:

    给定数列 ({a_n}) ,支持两种操作:

    • 在数列尾添加一个数 (x) ,数列长度变成 (n+1) ;
    • 给定闭区间 ([l,r]) 和一个数 (x) ,求:

    [max_{i=l}^{r}left {left(igoplus_{j=i}^{n}a_j ight)igoplus x ight } ]

    Method:

    定义 (Xorsum_i)(igoplus_{i=1}^{n}a_i) ,即前缀异或和。我们显然可以得到

    [left(igoplus_{i=pos}^{n}a_i ight)igoplus x=Xorsum_{pos-1}igoplus Xorsum_n igoplus x ]

    (xigoplus x=0) , (x igoplus 0=x)

    我们发现 (Xorsum_nigoplus x) 是一个定值,我们只需要维护 (Xorsum_{pos-1}) 即可。

    考虑用可持久化0-1Trie树维护。与主席树思路相同 ,我们建立 (n+1) 个版本的0-1Trie树,查询的时候运用贪心的思路即可。

    可持久化线段树同样支持“前缀和”的思想,我们最后只需要在第 (r) 个版本的0-1Trie树上查找 (l) 位置即可。

    本题毒瘤卡常,本人人丑常数大,用了fread等各种卡常操作才通过。并且由于luogu评测姬的原因(大雾,已经通过的代码又会T掉woc。卡不过的话,开o2吧。

    Code:

    #include<bits/stdc++.h>
    #define Maxn 600010
    #define Maxdep 23
    #define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    inline void read(int &x)
    {
        int f=1;x=0;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();}
        x*=f;
    }
    int n,m;
    int sum[Maxn];
    struct trie
    {
        trie *chd[2];
        int symbl;
        trie()
        {
            for(int i=0;i<2;i++) chd[i]=NULL;
            symbl=0;
        }
    }*root[Maxn],tree[Maxn<<5],*tail;
    void Init(){tail=tree;} 
    void build(trie *&p,int dep)
    {
        p=new (tail++)trie();
        if(dep<0) return ;
        build(p->chd[0],dep-1);
    }
    void update(trie *&p,trie *flag,int dep,int i)
    {
        p=new (tail++)trie();
        if(flag) *p=*flag;
        if(dep<0) return (void)(p->symbl=i);
        int tmp=(sum[i]>>dep)&1;//判断是1还是0 
        if(!tmp) update(p->chd[0],flag?flag->chd[0]:NULL,dep-1,i);
        else update(p->chd[1],flag?flag->chd[1]:NULL,dep-1,i);
        if(p->chd[0]) p->symbl=std::max(p->symbl,p->chd[0]->symbl);
        if(p->chd[1]) p->symbl=std::max(p->symbl,p->chd[1]->symbl);
    }
    int query(trie *p,int x,int dep,int limit)
    {
        if(dep<0) return sum[p->symbl]^x;
        int tmp=(x>>dep)&1;
        if(p->chd[tmp^1]&&p->chd[tmp^1]->symbl>=limit) return query(p->chd[tmp^1],x,dep-1,limit);
        return query(p->chd[tmp],x,dep-1,limit);
    }
    signed main()
    {
        Init();
        read(n),read(m);
        build(root[0],Maxdep);
        for(int i=1,x;i<=n;i++)
        {
            read(x);
            sum[i]=sum[i-1]^x;
            update(root[i],root[i-1],Maxdep,i);
        } 
        for(int i=1;i<=m;i++)
        {
            char ch=getchar();
            while(ch!='A'&&ch!='Q') ch=getchar();
            if(ch=='A')
            {
                int x;
                read(x);
                n++;
                sum[n]=sum[n-1]^x;
                update(root[n],root[n-1],Maxdep,n);	
                continue;
            }	
            if(ch=='Q')
            {
                int l,r,x;
                read(l),read(r),read(x);
                int ans=query(root[r-1],sum[n]^x,Maxdep,l-1);
                printf("%d
    ",ans);
                continue;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    优先队列总结
    CodeForces 567D One-Dimensional Battle Ships
    CodeForces 567D One-Dimensional Battle Ships
    codeforces 1016B. Segment Occurrences
    codeforces 1016B. Segment Occurrences
    poj3249(求最长路)
    poj3249(求最长路)
    poj 2186
    2017年第八蓝桥杯C/C++ A组国赛 —— 第二题:生命游戏
    Fence Repair POJ
  • 原文地址:https://www.cnblogs.com/nth-element/p/11785037.html
Copyright © 2011-2022 走看看