板子:trie以及权值线段树查找异或

分类简述

一般的trie

并没有什么特别的,可以O(n)进行字符串匹配。

二进制trie

这不是做字符串匹配的,而是查找最大异或和,从高位贪心即可,高位不够补0

可持久化trie

单纯的给trie加个可持久化

权值线段树

二进制trie

注意:
- 充分理解在高层结点决策的思想,因为边才是权值。
- 直接一位对一位,调位置太麻烦了。
- 注意那个bool运算要转换成bool型才用^什么的。
- 写递归结构就可以了。

主席树

权值线段树的可持久化版本咯

代码

可持久化二进制trie

//就决定递归版了
struct TRIE
{
    int rt[maxv],np,ch[maxv][2],sz[maxv],val[maxv];
    void Build()
    {
        np=1;rt[0]=1;//因为后面会用到0这个点
        memset(rt,0,sizeof(rt));
        memset(ch,0,sizeof(ch));
        memset(sz,0,sizeof(sz));
        memset(val,0,sizeof(val));
    }
    int Newnode(int pre)
    {
        ++np;
        if(pre)
            ch[np][0]=ch[pre][0],ch[np][1]=ch[pre][1],sz[np]=sz[pre],val[np]=val[pre];
        else
            ch[np][0]=ch[np][1]=sz[np]=val[np]=0;
        return np;
    }
    void add(int pre,int &now,int x,int i)
    {
        now=Newnode(pre);
        sz[now]++;
        if(i>N)
        {
            val[now]++;
            return;
        }
        bool id=x&(1<<(N-i));
        add(ch[pre][id],ch[now][id],x,i+1);
    }
    int query(int lnow,int rnow,int x,int i)
    {
        if(i>N)return 0;
        bool id=x&(1<<(N-i));
        int ret;
        if(sz[ch[rnow][id^1]]-sz[ch[lnow][id^1]])
        {
            ret=query(ch[lnow][id^1],ch[rnow][id^1],x,i+1);
            ret=ret|(1<<(N-i));
        }
        else
        {
            ret=query(ch[lnow][id],ch[rnow][id],x,i+1);
            ret=ret&(~(1<<(N-i)));
        }
        return ret;
    }
}tri;

区间查询带偏移最大异或和

int DFS(int a,int b,int i)//这里是返回a+x的最优值 
{
    if(a==b)return a;
    int mid=(a+b)>>1;
    if( Q & (1<<i) )//第i位为1,那么我们希望a为0 
    {
        if(max(0,a-x)<=min(N,mid-x) && sgt.query(sgt.rt[l-1],sgt.rt[r],0,N,max(0,a-x),min(N,mid-x) ) )
            return DFS(a,mid,i-1);
        else
            return DFS(mid+1,b,i-1);
    }
    else
    {
        if(max(0,mid+1-x)<=min(N,b-x) && sgt.query(sgt.rt[l-1],sgt.rt[r],0,N,max(0,mid+1-x),min(N,b-x) ) )
            return DFS(mid+1,b,i-1);
        else
            return DFS(a,mid,i-1);
    }
}
int main()
{
    Init();
    while(m--)
    {
        scanf("%d%d%d%d",&Q,&x,&l,&r);
        printf("%d\n",Q^DFS(0, ( 1<<(oo+1) )-1 , oo ) );
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值