codeforces 979D. Kuro and GCD and XOR and SUM

codeforces

不大懂这个题怎么一群老哥跑的飞快/kk

异或最大值不难想到Trie,但是还有一个\(gcd\)的限制比较烦人,注意到\(x\leq 10^5\)\(x\)的因数个数不会太多,那么我们可以维护\(10^5\)个Trie,第\(k\)个表示所有的\(k\)的倍数的数组成的Trie,那么每次询问只需要询问第\(k\)个Trie即可,当然首先要保证\(k|x\)

还剩下一个\(v\leq s-x\)的限制,这个比较轻松,对Trie树上的所有点记录下其子树中的最小值,如果子树的最小值都不满足这个限制就没有必要继续询问下去了

预处理\(1- 10^5\)中的所有数的所有因数,这个可以\(O(nlogn)\)完成

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int ch[30002000][2],minx[30002000],root[100100],tot=0,val[30002000];
vector<int> fac[100100];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void insert(int &now,int x,int d)
{
    if (!now) {now=(++tot);minx[now]=maxd;}
    minx[now]=min(minx[now],x);
    if (d<0) {val[now]=x;return;}
    insert(ch[now][(x>>d)&1],x,d-1);
}

int query(int now,int lim,int x,int d)
{
    if (d<0) return val[now];
    int ch0=ch[now][0],ch1=ch[now][1];
    if ((!ch0) || (minx[ch0]>lim)) return query(ch1,lim,x,d-1);
    if ((!ch1) || (minx[ch1]>lim)) return query(ch0,lim,x,d-1);
    return query(ch[now][((x>>d)&1)^1],lim,x,d-1);
}

int main()
{
    rep(i,1,N)
        for (int j=i;j<=N;j+=i) fac[j].pb(i);
    int q=read();
    while (q--)
    {
        int op=read();
        if (op==1)
        {
            int x=read(),len=fac[x].size();
            rep(i,0,len-1)
            {
                int y=fac[x][i];
                insert(root[y],x,18);
            }
        }
        else
        {
            int x=read(),k=read(),s=read();
            if ((x%k) || (!minx[root[k]]) || (minx[root[k]]>s-x)) puts("-1");
            else printf("%d\n",query(root[k],s-x,x,18));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/encodetalker/p/11432829.html