CodeForces - 979D Kuro and GCD and XOR and SUM

CodeForces - 979D Kuro and GCD and XOR and SUM
题意:两个操作,1向数组中添加一个值x,2询问数组中的值满足所给条件的异或xi之后为最大值的值。
2操作输入xi,ki,si,在数组中找到一个值v满足ki|gcd(xi,v),并且xi+v<=si,在所有满足的v中选一个异或xi之后的最大值。
思路:异或最大,01字典树,而且还不用持久化,因为ki需要可以整除gcd(xi,v),所有只要ki可以整出xi,并且可以整除v即可,这样可以开100000个01字典树,每个字典树的根为root[i],代表可以被i整除的v值都放在以此为根的字典树中,需要动态开点,查询时直接在以root[ki]为根的字典树上找满足条件的值即可。注意输出-1的条件需要考虑全面。至于内存不太会开,RE就加。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int MAX_N=101000;
const int INF=0x3f3f3f3f;
int trie[10*MAX_N*21][2];
int minl[10*MAX_N*21],minx[MAX_N];
int root[MAX_N],tot;
void insert(int k1,int val,int deep){
    if(deep<0){
        minl[k1]=val;
        return;
    }
    int x=(val>>deep)&1;
    if(!trie[k1][x])
    trie[k1][x]=++tot;
    insert(trie[k1][x],val,deep-1);
    if(trie[k1][0])
        minl[k1]=min(minl[k1],minl[trie[k1][0]]);
    if(trie[k1][1])
        minl[k1]=min(minl[k1],minl[trie[k1][1]]);
}
int ask(int k,int deep,int xi,int si){
    if(deep<0)
        return minl[k];
    int x=(xi>>deep)&1;
    if(trie[k][x^1]&&minl[trie[k][x^1]]<=si-xi)
        return ask(trie[k][x^1],deep-1,xi,si);
    else
        return ask(trie[k][x],deep-1,xi,si);
}
int main(void){
    int q,i,j,x,xi,ki,si,op;
    scanf("%d",&q);
    memset(minx,INF,sizeof(minx));
    memset(minl,INF,sizeof(minl));
    //cout<<minl[1314]<<"\n";
    for(j=0;j<q;j++){
        scanf("%d",&op);
        if(op==1){
            scanf("%d",&x);
            //minx=min(minx,x);
            for(i=1;i*i<=x;i++){
                if(x%i!=0)
                    continue;
                if(root[i])
                    insert(root[i],x,19);
                else{
                    root[i]=++tot;
                    insert(root[i],x,19);
                }
                if(x<minx[i])
                    minx[i]=x;
                int y=x/i;
                if(i==y)
                    continue;
                if(root[y])
                    insert(root[y],x,19);
                else{
                    root[y]=++tot;
                    insert(root[y],x,19);
                }
                if(x<minx[y])
                    minx[y]=x;
            }
        }
        else{
            scanf("%d%d%d",&xi,&ki,&si);
            if(xi%ki!=0||minx[ki]>si-xi||!root[ki]){
                printf("-1\n");
                continue;
            }
            int ans=ask(root[ki],19,xi,si);
            if(ans==INF)
                printf("-1\n");
            else
                printf("%d\n",ans);
        }
    }
    return 0;
}
发布了62 篇原创文章 · 获赞 6 · 访问量 1947
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章