LA3699 - Harmony Forever

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1700

  维护一个数集,支持两个操作:

    B x:插入一个数x

    A x:查询在mod x意义下最小的数的插入时间,如果有多个输出最近的。

  x的范围是[1,500000]。操作数≤40000。

  因为x的范围比较小,我们可以分块。另lim=2500。

  对于x<lim,我们暴力维护一个数组exist[i][j],代表在mod i意义下等于j的最近位置,插入一次用O(lim)的时间更新,查询O(1)。

  对于x≥lim,我们枚举答案对于除以x的商i,易知商≤500000/lim,然后求lower_bound(x×i),更新答案。用splay实现,插入O(log(n)),查询O(log(n)×500000/lim)。

#include<bits/stdc++.h>
using namespace std;
const int maxn=40015,maxv=500015,lim=2500;
struct Tsplay{
    struct Tnode{
        int n,val;Tnode *f,*c[2];
        void link(Tnode *newf,int newn){
            n=newn;f=newf;
            if (n!=2) f->c[n]=this;
        }
    }*null,*root,T[maxn];
    int tot;
    void clear(){
        tot=0;root=null=T;null->val=-1;
        null->c[0]=null->c[1]=null;
    }
    Tnode *newnode(int v){
        Tnode *cur=T+(++tot);
        cur->n=2;cur->val=v;
        cur->c[0]=cur->c[1]=cur->f=null;
        return cur;
    }
    void rotate(Tnode *x){
        Tnode *y=x->f,*z=y->f;int nx=x->n,ny=y->n;
        x->link(z,ny);x->c[!nx]->link(y,nx);y->link(x,!nx);
    }
    void splay(Tnode *x){
        while (x->n!=2){
            x->n==x->f->n?rotate(x->f):rotate(x);
            if (x->n!=2) rotate(x);
        }
        root=x;
    }
    void insert(int v){
        if (root==null){root=newnode(v);return;}
        Tnode *x=root;
        while (1){
            if (v<x->val){
                if (x->c[0]==null){x->c[0]=newnode(v);x->c[0]->link(x,0);splay(x->c[0]);return;}
                else x=x->c[0];
            }
            else{
                if (x->c[1]==null){x->c[1]=newnode(v);x->c[1]->link(x,1);splay(x->c[1]);return;}
                else x=x->c[1];
            }
        }
    }
    int lower_bound(int v){
        if (root==null) return -1;
        Tnode *x=root,*res=null;
        while (x!=null){
            if (x->val>=v){res=x;x=x->c[0];}
            else x=x->c[1];
        }
        if (res!=null) splay(res);
        return res->val;
    }
}splay;
int n,vis[maxv],exist[lim][lim];
void insert(int x,int t){
    if (!vis[x]) splay.insert(x);vis[x]=t;
    for (int i=1;i<lim;++i) exist[i][x%i]=t;
}
void query(int x){
    if (x<lim){
        for (int i=0;i<x;++i)
            if (exist[x][i]){printf("%d\n",exist[x][i]);return;}
        printf("-1\n");
    }
    else{
        int v=splay.lower_bound(0),d=v;
        if (v==-1){printf("-1\n");return;}
        for (int y,i=x;(y=splay.lower_bound(i))!=-1;i+=x)
            if (y-i<d||(y-i==d&&vis[y]>vis[v])){v=y;d=y-i;}
        printf("%d\n",vis[v]);
    }
}
void solve(){
    splay.clear();int tim=0;
    memset(vis,0,sizeof(vis));
    memset(exist,0,sizeof(exist));
    for (int i=1;i<=n;++i){
        char op[5];int x;
        scanf("%s%d",op,&x);
        switch (op[0]){
            case 'B':insert(x,++tim);break;
            case 'A':query(x);break;
        }
    }
}
int main(){
    int cases=0;
    while (scanf("%d",&n)!=EOF&&n){
        if (++cases!=1) printf("\n");
        printf("Case %d:\n",cases);
        solve();
    }
    return 0;
}
my code

 

posted @ 2015-08-11 10:01  iamCYY  阅读(275)  评论(0编辑  收藏  举报