CodeForces - 482D Kuro and GCD and XOR and SUM(01字典树)

链接:CodeForces - 482D Kuro and GCD and XOR and SUM

题意:

给一个空的集合 a a ,共有 q    ( 2 q 1 0 5 ) q\;(2\le q\le 10^5) 次操作,分为以下 2 2 种操作

  • 1    u i 1\;u_i :将 u i u_i 加入到集合 a a    ( 1 u i 1 0 5 ) \;(1\le u_i\le 10^5)
  • 2    x i    k i    s i 2\;x_i\;k_i\;s_i :在集合 a a 中找到一个数 v v ,满足 k i gcd ( x i , v ) ,    x i + v s i k_i|\gcd(x_i,v),\;x_i+v\le s_i x i v x_i\oplus v 最大,并输出 v v ,若找不到,则输出 1    ( 1 x i , k i , s i 1 0 5 ) -1\;(1\le x_i,k_i,s_i\le10^5)


分析:

首先第一个条件 k i gcd ( x i , v ) k_i|\gcd(x_i,v) ,也就是要求满足 k i x i k_i|x_i k i v k_i|v ,所以若不满足 k i x i k_i|x_i ,可以直接输出 1 -1

后两个条件: x i + v s i x_i+v\le s_i x i v x_i\oplus v 最大,可以在字典树上进行查找,为保证 x i + v s i x_i+v\le s_i (即 v s i x i v\le s_i-x_i ),可以再 设置一个变量 m i n _ v a l [ u ] min\_val[u] ,表示以 u u 为根结点的子树内存储的最大值

这样每次查询 即要尽可能与 x i x_i 异或最大,还要保证对应子树的 m i n _ v a l [ v ] s i x i min\_val[v]\le s_i-x_i


其次,为满足 k i v k_i|v ,可以 对每一个 k i k_i 值建一个01字典树(存储所有 k i k_i 的倍数,即能被 k i k_i 整除的数),对于新输入的 u i u_i ,要把 u i u_i 插入到其所有因数对应的树中,找到所有因数的时间只需要 O ( u i ) O(\sqrt {u_i})



以下代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=1e5+50;
const int INF=0x3f3f3f3f;
const int max_base=20;
int ch[maxn*200][2],val[maxn*200],min_val[maxn*200],tot;
struct bit_tire
{
    int root;
    void init()
    {
        ch[tot][0]=ch[tot][1]=0;
        val[tot]=0;
        min_val[tot]=INF;
        root=tot++;
    }
    void insert(int x)
    {
        int u=root;
        for(int i=max_base;i>=0;i--)
        {
            min_val[u]=min(x,min_val[u]);
            int c=(x>>i)&1;
            if(!ch[u][c])
            {
                ch[tot][0]=ch[tot][1]=0;
                val[tot]=0;
                min_val[tot]=INF;
                ch[u][c]=tot++;
            }
            u=ch[u][c];
        }
        min_val[u]=val[u]=x;
    }
    int query_max(int x,int y)   //查询该tire小于等于y的与x异或最大值
    {
        int u=root;
        for(int i=max_base;i>=0;i--)
        {
            int c=(x>>i)&1;
            if(ch[u][c^1]&&min_val[ch[u][c^1]]<=y)
                u=ch[u][c^1];
            else if(ch[u][c]&&min_val[ch[u][c]]<=y)
                u=ch[u][c];
            else
                return -1;
        }
        return val[u];
    }
}t[maxn];
void init()
{
    tot=1;
    for(int i=1;i<maxn;i++)
        t[i].init();
}
int main()
{
    init();
    int q,op,u,x,k,s;
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&u);
            int k=(int)round(sqrt(u));
            for(int i=1;i<=k;i++)
            {
                if(u%i==0)
                {
                    t[i].insert(u);
                    t[u/i].insert(u);
                }
            }
        }
        else
        {
            scanf("%d %d %d",&x,&k,&s);
            if(x%k!=0)
                printf("-1\n");
            else
                printf("%d\n",t[k].query_max(x,s-x));
        }
    }
    return 0;
}

发布了214 篇原创文章 · 获赞 40 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Ratina/article/details/99414135