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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章