zoukankan      html  css  js  c++  java
  • 2021“MINIEYE杯”中国大学生算法设计超级联赛(1)1006/HDU 6955 Xor sum

    https://acm.hdu.edu.cn/showproblem.php?pid=6955

    题意:

    找最短的异或和>=k的连续子序列

    先求前缀异或和a[]

    问题转化成求l和r(l<r),满足a[r]^a[l]>=k且r-l最小

    用字典树存储每个节点对应异或区间的最靠后的位置

    把0位置异或0加进字典树

    然后枚举右端点i

    先查询能以i为右端点的最靠后的左端点

    再把当前位置的前缀异或值加入字典树

    查询方式:

    从高到低枚举k的每一位,假设对应位当前前缀异或值是w(0或者1)

    如果k的这一位是1,那么必须要走w^1方向。

    如果k的这一位是0,那么先用w^1方向的最靠后位置更新,再走w方向。因为只要这一位的异或结果是1,就会满足>k的条件,只需要再找到这一位暂时相等,要通过后面的位决出大小的位置。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 100001
    
    int tr[N*30][2],mx[N*30],tot;
    int a[N]; 
    
    int bit[30];
    
    void add(int val,int pos)
    {
        int w,now=0;
        for(int j=29;j>=0;--j)
        {
            w=(val>>j)&1;
            if(!tr[now][w]) tr[now][w]=++tot;
            now=tr[now][w];
            mx[now]=pos;
        }
    }
    
    int main()
    {
        int T,n,k,al,ar,r,now,w;
        memset(mx,-1,sizeof(-1));
        scanf("%d",&T);
        while(T--)
        {
            al=1;
            ar=1e9;
            scanf("%d%d",&n,&k);    
            for(int i=0;i<30;++i) bit[i]=(k>>i)&1;
            for(int i=1;i<=n;++i) 
            {
                scanf("%d",&a[i]); 
                a[i]^=a[i-1];
            }
            add(0,0);
            for(int i=1;i<=n;++i)
            {            
                r=-1;
                now=0;
                for(int j=29;j>=0;--j)
                {
                    w=(a[i]>>j)&1;
                    if(!bit[j])
                    {
                        r=max(r,mx[tr[now][w^1]]);
                        now=tr[now][w];
                    }
                    else now=tr[now][w^1];
                    if(!now) break; 
                }
                r=max(r,mx[now]);
                if(r>-1 && i-r<ar-al)
                {
                    al=r;
                    ar=i;
                }
                add(a[i],i);
            }
            if(ar-al<n) printf("%d %d
    ",al+1,ar);
            else printf("-1
    ");
            for(int i=0;i<=tot;++i) 
            {
                mx[i]=-1;
                tr[i][0]=tr[i][1]=0;
            }
            tot=0;
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    Java实现 LeetCode 661 图片平滑器(暴力)
    Java实现 LeetCode 661 图片平滑器(暴力)
    PHP imagecolorat
    PHP imagecolorallocatealpha
    PHP imagecolorallocate
    PHP imagecharup
    PHP imagechar
    网格 | CSS Grid (Grid Layout)
    网格 | @media.grid (Media Queries)
    缩放背景图像 | CSS Background and Borders: Scaling background images (Backgrounds & Borders)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15071386.html
Copyright © 2011-2022 走看看