HDU5968 异或密码 —— 二分 + 边界的细节处理
题目链接: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
中xor表示位异或运算,对应C、C++、 Java等语言中的^运算。
小璐提出了M个询问,每个询问用一个整数 xi描述。
对于每个询问,晨晨需要找到序列{ai}的所有连续子序列,求出每个子序列异或的结果,找到所有的结果中与 xi之差的绝对值最小的一个,并告诉小璐相应子序列的长度。
若有多个满足条件的连续子序列,则告诉小璐这些子序列中最长的长度。
每组数据共两行。
第一行包含N+1个非负整数。其中第一个数为N,表示序列的长度;接下来N 个数,依次描述序列{ ai}中的每个数。
第二行包含M+1个整数。其中第一个数为M,表示询问的个数;接下来M个数 xi,每个数对应题目描述中的一个询问。
保证 1 <= N <= 100,1 <= M <= 100,ai <=
1024,|xi|
<= 1024,数据组数 <= 100。
2 1 1
2 0 2
3 1 2 4
3 10 5 1
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 异或密码 —— 二分 + 边界的细节处理的更多相关文章
- [HDU5968]异或密码
[HDU5968]异或密码 题目大意: 数据共\(T(T\le100)\)组.每组给定一个长度为\(n(n\le100)\)的非负整数序列\(A(A_i\le1024)\),\(m(m\le100)\ ...
- HDU-5968异或密码
超级传送门 题目描述: 晨晨在纸上写了一个长度为N的非负整数序列{ai}.对于这个序列的一个连续子序列{al,al+1,…,ar}晨晨可以求出其中所有数异或的结果 alxoral+1xor...xor ...
- hdu_5968_异或密码(预处理+二分)
题目链接:hdu_5968_异或密码 题意: 中午,不解释 题解: 前缀处理一下异或值,然后上个二分查找就行了,注意是unsigned long long #include<bits/stdc+ ...
- HDU 5968 异或密码
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- HDU 5968 异或密码 【模拟】 2016年中国大学生程序设计竞赛(合肥)
异或密码 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Des ...
- 异或密码---hdu5968(CCPC合肥,二分)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5968 思路:先把所有的连续异或值保存起来,排序,然后用二分找到距离x最近的那个点,判断即可: # ...
- 【Java面试真题】剑指Offer53.2——0~n-1中缺失的数字(异或、二分两种解法)
[Java实现]剑指Offer53.2--0~n-1中缺失的数字:面试真题,两种思路分享 前面有另一道面试题[Java实现]剑指offer53.1--在排序数组中查找数字(LeetCode34:在排序 ...
- HDU 1998 奇数阶魔方【模拟填数/注意边界和细节】
奇数阶魔方 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Wannafly Winter Camp 2020 Day 6H 异或询问 - 二分
给定一个长 \(n\) 的序列 \(a_1,\dots,a_n\),定义 \(f(x)\) 为有多少个 \(a_i \leq x\) 有 \(q\) 次询问,每次给定 \(l,r,x\),求 \(\s ...
随机推荐
- Nginx+keepalived双机热备(主从模式)
简单介绍: Keepalived是Linux下面实现VRRP备份路由的高可靠性运行软件,能够真正做到 主服务器和备份服务器故障时IP瞬间无缝交接; Keepalived的目的是模拟路由器的高可用; H ...
- 2017 [六省联考] T1 期末考试
4868: [Shoi2017]期末考试 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 842 Solved: 385[Submit][Status ...
- python--文件处理1
1. 读取文件 方法: all_the_text = open('thefile.txt').read() 但是为了安全起见还是给打开的文件对象指定一个名字,这样在完成之后可以迅速关掉,防止无 ...
- 托管和非托管转换新方法:Marshaling Library(zz) 【转】
托管和非托管转换新方法:Marshaling Library(zz) 托管和非托管转换新方法:Marshaling Library(zz) http://hi.baidu.com/superql/bl ...
- String空格删除和java删除字符串最后一个字符的几种方法
1. String.trim()trim()是去掉首尾空格2.str.replace(" ", ""); 去掉所有空格,包括首尾.中间复制代码 代码如下:Str ...
- Git 常用场景操作
git init 在本地新建一个repo,进入一个项目目录,执行git init,会初始化一个repo,并在当前文件夹下创建一个.git文件夹. git clone 获取一个u ...
- sql_视图和函数
创建视图: create view xxx as select * from userinfo; 删除视图: drop view xxx 修改视图: alter view xxx as selete ...
- sql的一些知识_order by
注释 SELECT name FROM userinfo #这是注释 /* 这是多行注释 */ order by 排序() SELECT username FROM userinfo ORDER BY ...
- 深入解析Ajax——系列(一)
常常写脚本的人.有时候会用到$ajax,有时候也会用到$post和$get,这几个方法都是用来从Webserver上获取静态的数据文件. jQuery对ajax操作进行了封装,在jquery中$.aj ...
- C 标准库 - <signal.h>
C 标准库 - <signal.h> 简介 signal.h 头文件定义了一个变量类型 sig_atomic_t.两个函数调用和一些宏来处理程序执行期间报告的不同信号. 库变量 下面是头文 ...