题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5968

异或密码

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1214    Accepted Submission(s): 404

Problem Description
晨晨在纸上写了一个长度为N的非负整数序列{ai}。对于这个序列的一个连续子序列{al,al+1,…,ar}晨晨可以求出其中所有数异或的结果 alxoral+1xor...xorar其
中xor表示位异或运算,对应C、C++、 Java等语言中的^运算。
小璐提出了M个询问,每个询问用一个整数 xi描述。
对于每个询问,晨晨需要找到序列{ai}的所有连续子序列,求出每个子序列异或的结果,找到所有的结果中与 xi之差的绝对值最小的一个,并告诉小璐相应子序列的长度。
若有多个满足条件的连续子序列,则告诉小璐这些子序列中最长的长度。
 
Input
包含多组测试数据,第一行一个正整数T,表示数据组数。
每组数据共两行。
第一行包含N+1个非负整数。其中第一个数为N,表示序列的长度;接下来N 个数,依次描述序列{ ai}中的每个数。
第二行包含M+1个整数。其中第一个数为M,表示询问的个数;接下来M个数 xi,每个数对应题目描述中的一个询问。
保证 1 <= N <= 100,1 <= M <= 100,ai <=
1024,|xi|
<= 1024,数据组数 <= 100。
 
Output
对于每组数据输出M + 1行。前M行对应晨晨M个询问的回答,第M + 1行为空行
 
Sample Input
2
2 1 1
2 0 2
3 1 2 4
3 10 5 1
 
Sample Output
2
1

3
2
1

题解:

1.先预处理出连续子序列的异或值和长度。

2.由于异或值最大只能为2048,所以可以用优先队列保存每个异或值下的长度,用一个数组s[]保存有哪些长度,然后再对s[]数组去重(sort()+unique())。当然不推荐这种做法,因为每个异或值下,只有最大长度是有用的,所以再保存其他值就浪费了空间。推荐的做法是:将每个连续子序列的异或值和长度放到一个结构体里面,然后再对结构体进行排序,最后手动去重。

3.对于每次操作,使用二分试图去找到第一个异或值大于等于x的结构体,然后就是一些有关二分以及其他的细节处理,不细讲。

数组 + 优先队列(不推荐):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
//#define LOCAL
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; int a[];
int n, m, cnt;
priority_queue<int>q[maxn]; int s[*]; int sch(int x)
{
int l = , r = cnt;
while(l<r)
{
int mid = (l+r)>>;
if(s[mid]>=x)
r = mid;
else
l = mid + ;
}
return r;
} void init()
{
cnt = ;
scanf("%d",&n);
for(int i = ; i<=n; i++)
scanf("%d",&a[i]), a[i] = a[i]^a[i-]; for(int i = ; i<maxn; i++)
while(!q[i].empty()) q[i].pop(); for(int i = ; i<=n; i++)
for(int j = i; j<=n; j++)
{
s[++cnt] = a[j]^a[i-];
q[a[j]^a[i-]].push(j-i+);
} sort(s+,s++cnt);
cnt = unique(s+,s++cnt) - (s+);
} void solve()
{
scanf("%d",&m);
for(int i = ; i<m; i++)
{
int x, ans;
scanf("%d",&x);
int t = sch(x); if(s[t]==x)
ans = q[x].top();
else if(t==)
ans = q[s[t]].top();
else
{
if(abs(x-s[t])==abs(x-s[t-]))
ans = max(q[s[t]].top(), q[s[t-]].top());
else if(abs(x-s[t])<abs(x-s[t-]))
ans = q[s[t]].top();
else
ans = q[s[t-]].top();
}
cout<<ans<<endl;
}
cout<<endl;
} int main()
{
#ifdef LOCAL
freopen("", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d",&T);
while(T--)
{
init();
solve();
}
}

结构体:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
//#define LOCAL
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; int a[];
int n, m, cnt; struct node
{
int val, len;
bool operator<(node &xx)const{
if(val==xx.val) return len>xx.len;
return val<xx.val;
}
}s[*]; void init()
{
scanf("%d",&n);
for(int i = ; i<=n; i++)
scanf("%d",&a[i]), a[i] = a[i]^a[i-]; cnt = ;
for(int i = ; i<=n; i++)
for(int j = i; j<=n; j++)
s[++cnt].val = a[i-]^a[j], s[cnt].len = j-i+; n = ;
sort(s+,s++cnt);
for(int i = ; i<=cnt; i++)
if(i== || s[i].val!=s[i-].val)
s[++n] = s[i];
} int sch(int x)
{
int l = , r = n;
while(l<r)
{
int mid = (l+r)>>;
if(s[mid].val>=x)
r = mid;
else
l = mid + ;
}
return r;
} void solve()
{
scanf("%d",&m);
for(int i = ; i<m; i++)
{
int x, ans;
scanf("%d",&x);
int t = sch(x); if(s[t].val==x)
ans = s[t].len;
else if(t==)
ans = s[].len;
else
{
if( abs(x-s[t].val)==abs(x-s[t-].val) )
ans = max( s[t].len, s[t-].len );
else if( abs(x-s[t].val)<abs(x-s[t-].val) )
ans = s[t].len;
else
ans = s[t-].len;
}
cout<<ans<<endl;
}
cout<<endl;
} int main()
{
#ifdef LOCAL
freopen("", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d",&T);
while(T--)
{
init();
solve();
}
}

HDU5968 异或密码 —— 二分 + 边界的细节处理的更多相关文章

  1. [HDU5968]异或密码

    [HDU5968]异或密码 题目大意: 数据共\(T(T\le100)\)组.每组给定一个长度为\(n(n\le100)\)的非负整数序列\(A(A_i\le1024)\),\(m(m\le100)\ ...

  2. HDU-5968异或密码

    超级传送门 题目描述: 晨晨在纸上写了一个长度为N的非负整数序列{ai}.对于这个序列的一个连续子序列{al,al+1,…,ar}晨晨可以求出其中所有数异或的结果 alxoral+1xor...xor ...

  3. hdu_5968_异或密码(预处理+二分)

    题目链接:hdu_5968_异或密码 题意: 中午,不解释 题解: 前缀处理一下异或值,然后上个二分查找就行了,注意是unsigned long long #include<bits/stdc+ ...

  4. HDU 5968 异或密码

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  5. HDU 5968 异或密码 【模拟】 2016年中国大学生程序设计竞赛(合肥)

    异或密码 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Des ...

  6. 异或密码---hdu5968(CCPC合肥,二分)

     题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5968 思路:先把所有的连续异或值保存起来,排序,然后用二分找到距离x最近的那个点,判断即可:   # ...

  7. 【Java面试真题】剑指Offer53.2——0~n-1中缺失的数字(异或、二分两种解法)

    [Java实现]剑指Offer53.2--0~n-1中缺失的数字:面试真题,两种思路分享 前面有另一道面试题[Java实现]剑指offer53.1--在排序数组中查找数字(LeetCode34:在排序 ...

  8. HDU 1998 奇数阶魔方【模拟填数/注意边界和细节】

    奇数阶魔方 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  9. Wannafly Winter Camp 2020 Day 6H 异或询问 - 二分

    给定一个长 \(n\) 的序列 \(a_1,\dots,a_n\),定义 \(f(x)\) 为有多少个 \(a_i \leq x\) 有 \(q\) 次询问,每次给定 \(l,r,x\),求 \(\s ...

随机推荐

  1. 第2章 Spring Boot 文档

    Spring Boot 文档 本节简要介绍了Spring Boot文档,是整个文档的参考指南. 您可以完整阅读本参考指南,或者如果您不感兴趣的话可以跳过该部分. 1. 关于文档 Spring Boot ...

  2. 关于 Bellman-Ford 与 Floyd 算法的一点感想

    在四种常用的最短路算法 Dijkstra, SPFA, floyd, Bellman-Ford 中, Dijks 和 SPFA 的使用较为普遍, 对大多数人来说, 也较为熟悉. 然而, floyd 与 ...

  3. electron入门教程

    1.atom/electron github: https://github.com/atom/electron 中文文档: https://github.com/atom/electron/tree ...

  4. paramiko执行命令超时的问题

    问题:paramiko远程执行命令,需要等到命令返回信息,如果命令执行时间比较长,返回信息就需要等很久 方案:1.使用nohup + 待执行命令 + & ,使用后台执行的方式,应该可以快速返回 ...

  5. display:flex不兼容Android、Safari低版本的解决方案 【flex布局】

    引自 http://www.cnblogs.com/shimily/articles/7943370.html <!DOCTYPE html> <html lang="en ...

  6. ARC forbids Objective-C objects in structs or unions

    解决方法有二种: 1.在出错的地方加入__unsafe_unretained 2.关闭系统ARC.1.点击project   2.点击Build Setting    3.找到其以下的Objetive ...

  7. Python生成8位随机字符串的一些方法

    #第一种方法 import random import string seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP ...

  8. javascript 高级编程系列 - 创建对象

    1. 工厂模式 function createPerson(name, age) { var obj = {}; obj.name = name; obj.age = age; obj.getName ...

  9. SVProgressHUD 用法一

    SVProgressHUD 用法一  SVProgressHUD 是一个第三方的控件,是一个弹出提示层,用来提示 网络加载 或 提示对错,看下面图,你就明白了:     那么,SVProgressHU ...

  10. Jenkins 搭建

    持续集成(CI continuous integration) 可以做什么? 自动构建.定时触发,或由某个事件触发.比如可以做 daily build,或每次代码提交时触发.这样可以最早发现代码编译和 ...