zoukankan      html  css  js  c++  java
  • 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

    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的结构体,然后就是一些有关二分以及其他的细节处理,不细讲。



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

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 #define ms(a,b) memset((a),(b),sizeof((a)))
     13 //#define LOCAL
     14 using namespace std;
     15 typedef long long LL;
     16 const int INF = 2e9;
     17 const LL LNF = 9e18;
     18 const int mod = 1e9+7;
     19 const int maxn = 2048+10;
     20 
     21 int a[110];
     22 int n, m, cnt;
     23 priority_queue<int>q[maxn];
     24 
     25 int s[110*110];
     26 
     27 int sch(int x)
     28 {
     29     int l = 1, r = cnt;
     30     while(l<r)
     31     {
     32         int mid = (l+r)>>1;
     33         if(s[mid]>=x)
     34             r = mid;
     35         else
     36             l = mid + 1;
     37     }
     38     return r;
     39 }
     40 
     41 void init()
     42 {
     43     cnt = 0;
     44     scanf("%d",&n);
     45     for(int i = 1; i<=n; i++)
     46         scanf("%d",&a[i]), a[i] = a[i]^a[i-1];
     47 
     48     for(int  i = 0; i<maxn; i++)
     49         while(!q[i].empty()) q[i].pop();
     50 
     51     for(int i = 1; i<=n; i++)
     52     for(int j = i; j<=n; j++)
     53     {
     54         s[++cnt] = a[j]^a[i-1];
     55         q[a[j]^a[i-1]].push(j-i+1);
     56     }
     57 
     58     sort(s+1,s+1+cnt);
     59     cnt = unique(s+1,s+1+cnt) - (s+1);
     60 }
     61 
     62 void solve()
     63 {
     64     scanf("%d",&m);
     65     for(int i = 0; i<m; i++)
     66     {
     67         int x, ans;
     68         scanf("%d",&x);
     69         int t = sch(x);
     70 
     71         if(s[t]==x)
     72             ans = q[x].top();
     73         else if(t==1)
     74             ans = q[s[t]].top();
     75         else
     76         {
     77             if(abs(x-s[t])==abs(x-s[t-1]))
     78                 ans = max(q[s[t]].top(), q[s[t-1]].top());
     79             else if(abs(x-s[t])<abs(x-s[t-1]))
     80                 ans = q[s[t]].top();
     81             else
     82                 ans = q[s[t-1]].top();
     83         }
     84         cout<<ans<<endl;
     85     }
     86     cout<<endl;
     87 }
     88 
     89 int main()
     90 {
     91 #ifdef LOCAL
     92     freopen("1", "r", stdin);
     93 //      freopen("output.txt", "w", stdout);
     94 #endif
     95     int T;
     96     scanf("%d",&T);
     97     while(T--)
     98     {
     99         init();
    100         solve();
    101     }
    102 }
    View Code


    结构体:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 #define ms(a,b) memset((a),(b),sizeof((a)))
     13 //#define LOCAL
     14 using namespace std;
     15 typedef long long LL;
     16 const int INF = 2e9;
     17 const LL LNF = 9e18;
     18 const int mod = 1e9+7;
     19 const int maxn = 2048+10;
     20 
     21 int a[110];
     22 int n, m, cnt;
     23 
     24 struct node
     25 {
     26     int val, len;
     27     bool operator<(node &xx)const{
     28         if(val==xx.val) return len>xx.len;
     29         return val<xx.val;
     30     }
     31 }s[110*110];
     32 
     33 void init()
     34 {
     35     scanf("%d",&n);
     36     for(int i = 1; i<=n; i++)
     37         scanf("%d",&a[i]), a[i] = a[i]^a[i-1];
     38 
     39     cnt = 0;
     40     for(int i = 1; i<=n; i++)
     41     for(int j = i; j<=n; j++)
     42         s[++cnt].val = a[i-1]^a[j], s[cnt].len = j-i+1;
     43 
     44     n = 0;
     45     sort(s+1,s+1+cnt);
     46     for(int i = 1; i<=cnt; i++)
     47         if(i==1 || s[i].val!=s[i-1].val)
     48             s[++n] = s[i];
     49 }
     50 
     51 int sch(int x)
     52 {
     53     int l = 1, r = n;
     54     while(l<r)
     55     {
     56         int mid = (l+r)>>1;
     57         if(s[mid].val>=x)
     58             r = mid;
     59         else
     60             l = mid + 1;
     61     }
     62     return r;
     63 }
     64 
     65 void solve()
     66 {
     67     scanf("%d",&m);
     68     for(int i = 0; i<m; i++)
     69     {
     70         int x, ans;
     71         scanf("%d",&x);
     72         int t = sch(x);
     73 
     74         if(s[t].val==x)
     75             ans = s[t].len;
     76         else if(t==1)
     77             ans = s[1].len;
     78         else
     79         {
     80             if( abs(x-s[t].val)==abs(x-s[t-1].val) )
     81                 ans = max( s[t].len, s[t-1].len );
     82             else if( abs(x-s[t].val)<abs(x-s[t-1].val) )
     83                 ans = s[t].len;
     84             else
     85                 ans = s[t-1].len;
     86         }
     87         cout<<ans<<endl;
     88     }
     89     cout<<endl;
     90 }
     91 
     92 int main()
     93 {
     94 #ifdef LOCAL
     95     freopen("1", "r", stdin);
     96 //      freopen("output.txt", "w", stdout);
     97 #endif
     98     int T;
     99     scanf("%d",&T);
    100     while(T--)
    101     {
    102         init();
    103         solve();
    104     }
    105 }
    View Code
  • 相关阅读:
    HDU 4825 Xor Sum
    Linux下使用Crontab定时执行脚本
    HDU 4824 Disk Schedule
    Educational Codeforces Round 26 D. Round Subset 动态规划
    POJ 1833 排列
    HDU 1716 全排列
    HDU 1027 全排列
    Educational Codeforces Round 26 A C 之Python
    ACM输入输出之python
    标准C程序设计七---102
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538646.html
Copyright © 2011-2022 走看看