• P7502 「HMOI R1」不知道是啥的垃圾题


    一道很有启发性的题目。

    考虑到由于是自然数对的比较,所以我们不能直接用 (01 ext{Trie})

    但是考虑到我们可以将 ( ext{Trie}) 转换成有 (4) 个出边的,每一个出边表示数对当前位的 (01) 情况。

    然后你考虑查询,对于当前位置,存在一种大于的情况,两种等于的情况,一种小于的情况。

    考虑到大于的情况我们可以直接计数,等于的情况就需要递归了,但是由于我们每一层都需要递归两次,效率过低,这该怎么办?

    考虑到我们大于情况是只需要数量的,我们可以考虑不建儿子,这样的话对于每一个点,我们可以将 (00)(11) 合并,(01)(10) 合并。这样无论是怎样的情况,等于的递归就只需要进入一个节点即可。

    然后每一个节点只需要储存一个数在当前位是 (0)(1) 的个数就行了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+5,K=63;
    int n;
    struct Trie{
    	int rt,tot;Trie(){rt=tot=1;}
    	struct Node{int son[2],size[2];}tr[N*K];
    	void insert(long long x,long long y,int z){
    		int u=rt;
    		for(int i=K;i>=0;--i){
    			int tx=((x>>i)&1),ty=((y>>i)&1);
    			if(!tr[u].son[tx^ty]) tr[u].son[tx^ty]=++tot;
    			u=tr[u].son[tx^ty],tr[u].size[tx]+=z;
    		}
    	}
    	int query(long long x,long long y){
    		int u=rt,res=0;
    		for(int i=K;i>=0;--i){
    			int tx=((x>>i)&1),ty=((y>>i)&1);
    			res+=tr[tr[u].son[tx^ty^1]].size[tx^1];
    			u=tr[u].son[tx^ty];
    		}
    		return res;
    	}
    }t;
    signed main(){
    	cin>>n;
    	for(int i=1;i<=n;++i){
    		int opt;long long x,y;
    		scanf("%d%lld%lld",&opt,&x,&y);
    		if(opt==1) t.insert(x,y,1);
    		else if(opt==2) t.insert(x,y,-1);
    		else printf("%d
    ",t.query(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    [HAOI2006] 数字序列
    [HAOI2012] 外星人
    [HAOI2012] 高速公路
    [HAOI2007] 覆盖问题
    [HAOI2007] 分割矩阵
    [HAOI2007] 上升序列
    牛客练习赛58 D 迷宫
    牛客练习赛58 F XOR TREE
    牛客练习赛58 E 最大GCD
    牛客练习赛58 C 矩阵消除游戏
  • 原文地址:https://www.cnblogs.com/Point-King/p/15338853.html
Copyright © 2020-2023  润新知