[LightOJ 1269] Consecutive_Sum (Trie树妙用)
来源:互联网 发布:linux http管理 编辑:程序博客网 时间:2024/06/08 16:17
LightOJ - 1269
题意是给你一个序列,求子序列区间异或起来的最大值和最小值
首先可以利用类似前缀和的形式预处理一下,inpt[i]^=inpt[i-1]
然后一段区间[l,r]的异或值就等于 inpt[r]^inpt[l-1]
然后问题就转化成了求区间两个数,异或的最大值和最小值,接下来就是问题的关键
显然这是一个位运算的题目,通常都要按位,从高位到低位来考虑
先求最大值,如果某个数的第 i位是 1的话,那么就尽可能地在其他数中找第 i位为 0的,这样贪心保证结果尽可能地大
很不幸朴素去找的话,时间是 O(n^2)
于是我们把数处理成字符串存在一个 trie树里,然后把当前数与 trie树进行匹配
匹配过程就是从高位到低位,从trie树的根向下走,每次走到当前位相反的位置,这样保证当前位尽可能地为 1(最大)
比如当前数当前位为 1,如果能接下来 trie树上能走到 0,那么就走,否则只能走 1
求最小值过程类似,只不过是尽量走到相同的位置,把当前位消成 0
一个数先匹配,完了以后再把数加到 trie树里。这是为了防止求最小的时候恰好能匹配到刚加进去的数,得到结果 0
#include <cstdio>#include <iostream>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <map>#include <set>#include <queue>using namespace std;typedef pair<int,int> Pii;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define LL long long#define ULL unsigned long longint maxx(int a,int b){return a>b?a:b;}int minn(int a,int b){return a<b?a:b;}int abss(int a){return a<0?(-a):a;}const int maxn=50000+10,noden=50000*32+10;struct trnode{ int now,nxt[2];};int N,trien;int inpt[maxn];trnode trie[noden];int find(int,int);void insert(int);//void bpri(int);int main(){ int T; scanf("%d", &T); for(int ck=1; ck<=T; ck++) { trien=0; CLR(trie); scanf("%d", &N); for(int i=1; i<=N; i++) { scanf("%d", &inpt[i]); inpt[i]^=inpt[i-1]; } insert(0); int sum=0,tmax=-1,tmin=(-1)^(1<<31); for(int i=1; i<=N; i++) { tmax=maxx(tmax, find(inpt[i],0)); tmin=minn(tmin, find(inpt[i],1)); insert(inpt[i]); } printf("Case %d: %d %d\n", ck, tmax, tmin); } return 0;}int find(int num,int xnum){ int np=0; for(int mask=1<<30; mask; mask>>=1) { int now=(num&mask)?1:0; now^=xnum; if(trie[np].nxt[now^1]) np=trie[np].nxt[now^1]; else if(trie[np].nxt[now]) np=trie[np].nxt[now]; else break; num^=(trie[np].now)?mask:0; } return num;}void insert(int num){ int np=0; for(int mask=1<<30; mask; mask>>=1) { int now=(num&mask)?1:0; if(trie[np].nxt[now]) { np=trie[np].nxt[now]; } else { trie[np].nxt[now]=++trien; np=trien; trie[np].now=now; } }}//void bpri(int num)//{// int stack[50],len=0;// while(num)// {// stack[++len]=num&1? 1: 0;// num>>=1;// }// while(len) printf("%d", stack[len--]);// puts("");//}
0 0
- [LightOJ 1269] Consecutive_Sum (Trie树妙用)
- lightoj 1269(trie)
- lightoj 1114(trie)
- lightoj 1224(trie)
- Trie树trie(前缀)
- Trie树(压缩Trie树及Double-Array Trie)
- hihocoder-1014 Trie树(Trie树)
- hihoCoder 1014 Trie树 (Trie)
- LightOJ 1269 Consecutive Sum(字典树)
- 连续子串最大最小异或值 Trie+Xor LightOJ 1269 Consecutive Sum
- Trie树(HDOJ1075)
- 字典树(Trie)
- Trie(字典)树
- Trie树(SOJ3336)
- 字典树(Trie)
- 字典树(trie)
- 字典树(Trie)
- POJ3630(Trie树)
- backbone ——find方法应用
- Java基础学习第四天——选择与循环结构
- Centos下zookeeper安装配置
- 今天开始把一些心得记录下来!
- return和break的区别(附带源代码)
- [LightOJ 1269] Consecutive_Sum (Trie树妙用)
- Java 获取指定时间的前一天Date
- 学习理论-模型选择-1-问题引入
- bzoj 2429(最小瓶颈生成树)
- 直接插入排序
- 理解 Keystone 核心概念 - 每天5分钟玩转 OpenStack(18)
- 续前篇-关于逆波兰表达式的计算
- (大一下)第一章-数组
- 一