• 字典树andXOR*


    A.HDU 4825

    你需要写一种数据结构:

    • 往其中加入一个正整数;
    • 找出一个正整数,使得该数与询问数的异或结果最大。

    (nle 10^5)

    将数按二进制从高位到低位插入字典树。
    查询时从高位往低位贪心。

    Code

    #include<cstdio>
    using namespace std;
    const int maxn=100003,maxlog=33;
    int t[maxn*maxlog][2],cnt;
    void insert(long long x){
    	int p=1;
    	for(int i=32;i>=0;i--){
    		int nxt=(x>>i)&1;
    		if(!t[p][nxt])t[p][nxt]=++cnt;
    		p=t[p][nxt];
    	}
    }
    long long query(long long x){
    	int p=1;
    	long long ret=0;
    	for(int i=32;i>=0;i--){
    		int nxt=!((x>>i)&1);
    		if(t[p][nxt])p=t[p][nxt],ret|=(long long)nxt<<i;
    		else p=t[p][!nxt],ret|=(long long)(!nxt)<<i;
    	}
    	return ret;
    }
    int n,m;
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int TT=1;TT<=T;TT++){
    		scanf("%d%d",&n,&m);
    		cnt=1;
    		for(int i=0;i<=n*maxlog;i++)t[i][0]=t[i][1]=0;
    		for(int i=1;i<=n;i++){
    			long long x;
    			scanf("%lld",&x);
    			insert(x);
    		}
    		printf("Case #%d:
    ",TT);
    		while(m--){
    			long long x;
    			scanf("%lld",&x);
    			printf("%lld
    ",query(x));
    		}
    	}
    	return 0;
    }
    

    B. HDU 5536

    有一个序列 (s) ,求 (max_{i,j,k,i≠j≠k} (s_i+s_j) oplus s_k)
    (1≤T≤1000)
    (3≤n≤1000)
    (0≤si≤10^9)
    There are at most (10) testcases with (n>100)
    ( ext{Time Limit=9s})

    直接 (O(n^2log n)) 暴力插字典树。

    C. BZOJ 4260

    有一个序列 (A) ,求 (max ((A[l_1] oplus A[l_1+1] oplus dots oplus A[r_1])+(A[l_2] oplus A[l_2+1] oplus dots oplus A[r_2]))(1le l_1le r_1<l_2le r_2le n))
    (nle 4*10^5)

    处理出:
    (pre[i]=a[1] oplus a[2] oplus dots oplus a[i])
    (suf[i]=a[i] oplus a[i+1] oplus dots oplus a[n])
    (B[i]=max(max_{jle i}pre[i] oplus pre[j-1],B[i-1]))
    (C[i]=max(max_{j≥i}suf[i] oplus suf[j+1],C[i+1]))
    答案 (=max_{iin [1,n-1]}(B[i]+C[i+1]))

    D. POJ 3764

    有一棵树,有边权,求异或和最大的路径的异或和。

    (dp[i]) 为从1到 (i) 的路径的异或和,答案 (=max_{i,j}(dp[i] oplus dp[j]))
    请自己证明。

    E. HDU 4757

    一棵树, (Q) 次询问节点 (x) 到节点 (y) 的路径上点权与 (x) 的异或的最大值。

    可持久化trie

    F. HDU 5661

    (max_{ale xle b,cle yle d}(x oplus y)(a,b,c,dle 10^{18}))

    从高位往低位贪心。

    Code

    #include<cstdio>
    using namespace std;
    const int maxlog=60;
    bool valid(long long ans,int i,long long bit,long long l,long long r){
    	bit=ans|(bit<<i);
    	return (bit|((1ll<<i)-1))>=l&&bit<=r;
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	for(int TT=1;TT<=T;TT++){
    		long long a,b,c,d,ans1=0,ans2=0;
    		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
    		for(int i=59;i>=0;i--){
    			bool v10=valid(ans1,i,0,a,b),v11=valid(ans1,i,1,a,b),v20=valid(ans2,i,0,c,d),v21=valid(ans2,i,1,c,d);
    			if(v10&&v21)ans2|=1ll<<i;
    			else if(v11&&v20)ans1|=1ll<<i;
    			else if(v11&&v21)ans1|=1ll<<i,ans2|=1ll<<i;
    		}
    		printf("%lld
    ",ans1^ans2);
    	}
    	return 0;
    }
    

    G. BZOJ 4245

    给定一个长度为 (n) 的序列 (a[1],a[2],dots ,a[n]),请将它划分为 (m) 段连续的区间,设第 (i) 段的费用 (c[i]) 为该段内所有数字的异或和,则总费用为 (c[1] | c[2] | dots | c[m]) 。请求出总费用的最小值。

    记录一下前缀异或和,然后枚举一个高位,如果存在一个高位使得至少 (m) 个异或和为 (0) 且总异或和 ((prev[n]))(0) ,那么即可划分,此时这一位对答案的贡献为 (0) ,否则该位对答案的贡献为一个 (2) 的幂。

    I. J. 字典树在字符串上的应用,略

    K. HDU 4099

    (T=50000) 组询问,每次给出一个长度不超过40的数,求最小的斐波那契数,使得给定的数是这个数的前缀。如果前100000个数中没有符合条件的,输出-1。

    高精计算前100000个斐波那契数,只需存储前50位(类似double),然后全部插到字典树里。

  • 相关阅读:
    并发编程(一) 操作系统基础和进程
    操作系统发展史
    网络编程(三) 大文件传输与UDP通信
    网络编程(二)-socket套接字
    网络编程(一)
    排序算法之冒泡法
    第二章 算法基础 思考题2-1
    查找算法之二分查找
    排序算法之归并排序
    排序算法之插入排序
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10885610.html
Copyright © 2020-2023  润新知