zoukankan      html  css  js  c++  java
  • [Codeforces 979D] Kuro and GCD and XOR and SUM

    Brief Intro:

    1操作:添加一个数

    2操作:寻找一个数v,kiGCD(xi,v)xi+v≤si, 且v^xi最大

    Algorithm:

    以前做的关于异或和字符串的题目比较少,这题就当是补基础了吧

    此题对v的限制条件很多,其中V、Xi异或值最大我们发现是一类经典问题

    建立Trie树,贪心寻找答案即可

    为了使答案满足kiGCD(xi,v),我们对1e5个数都各自建立一棵Trie树,其中存放这个数的所有倍数

    为了满足另一个条件V<=Si-Xi,我们对于每棵树上的每个节点维护一个min值,存放能到达此点的最小的数列中的数

    这样也顺便解决了是K的倍数但不属于数列的数的问题(min数组初始化INF)

    这样在查找时在满足min值<=Si-Xi的前提下贪心即可

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN=1e5+10;
    const int INF=1<<27;
    
    bool mark[MAXN];
    int q,tr[MAXN*20*20][2],mmin[MAXN*20*20],cnt=MAXN;  //对CNT的初始化很重要
    vector<int> divi[MAXN];
    
    void Update(int cur,int x)
    {
        mmin[cur]=min(mmin[cur],x);
        for(int i=19;i>=0;i--)
        {
            bool d=(x&(1<<i));
            if(!tr[cur][d]) tr[cur][d]=cnt++;
            cur=tr[cur][d];mmin[cur]=min(mmin[cur],x);
        }
    }
    
    int Query(int x,int cur,int lim)
    {
        if(mmin[cur]>lim) return -1;
        long long ret=0;
        for(int i=19;i>=0;i--)
        {
            bool d=(x&(1<<i));d=!d;
            if(mmin[tr[cur][d]]<=lim)  //查看是否满足条件
                cur=tr[cur][d],ret+=d*(1<<i);
            else
                cur=tr[cur][!d],ret+=(!d)*(1<<i);
        }
        return ret;
    }
    
    int main()
    {
        scanf("%d",&q);
        for(int i=0;i<MAXN*20*20;i++) mmin[i]=INF;
        for(int i=1;i<MAXN;i++)
            for(int j=i;j<MAXN;j+=i)
                divi[j].push_back(i);
                
        for(int i=1;i<=q;i++)
        {
            int op,x,k,s;
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d",&x);
                if(mark[x]) continue;
                mark[x]=true;
                for(int j=0;j<divi[x].size();j++) Update(divi[x][j],x);  //将个数的所有倍数都加进Trie中
            }
            else
            {
                scanf("%d %d %d",&x,&k,&s);
                if(x%k){puts("-1");continue;}
                printf("%d
    ",Query(x,k,s-x));
            }
        }
        return 0;
    }

    Review:

    1、异或最值   <------->    01Trie树

    这两者之间的转换十分常用,需构建联系

    Trie树的存储,一般使用Trie[MAXN][2]的方式更方便

    其中01Trie树的MAXN要取大,要取到MAXN*20*20?(不确定,上界应该是MAXN*2^16?)

    2、对于Trie树cnt初始化的问题

    由于n棵Trie树已经有n个root,因此cnt应初始化为n+1!!!

    3、当有时准确建图、建树要耗费太多时间时,考虑先全加进去,再通过极值初始化筛去不符合的点或边

    ex:此处要想使得Trie树中X的倍数都来自于当前数列,不免会TLE

            因此可以先将全部倍数都加进去,而不在数列的倍数min值初始化为INF即可

  • 相关阅读:
    10个对Web开发者最有用的Python包
    9款最好的JavaScript压缩工具
    推荐15款制作 SVG 动画的 JavaScript 库
    2016年最好的15个Web设计和开发工具
    整理六百篇web前端知识混总
    9款免费的跨浏览器测试工具
    9个有用的和免费的工具来支持动态网页开发
    8个基本的引导工具的网页设计师
    11款CSS3动画工具的开发
    2016年某前端群题目答案参考
  • 原文地址:https://www.cnblogs.com/newera/p/9053726.html
Copyright © 2011-2022 走看看