HDU 3303 Harmony Forever

题意: 现有一个空的集合,有连续的 m 组操作

          B  x    将 x 加入集合

          A  x    询问集合中的元素 y % x 的取得最小值的 y

分析: 鸽巢定理+线段树

        然后对每个y,由鸽巢定理,连续的y+1个数中必然存在mod y相同的数,可以多区间查询,

        即[0, y - 1] [y , 2 * y - 1]   取最优解

        当y比较小的时候,直接遍历会更快,即当 y<log(n) 的时候采用遍历的方法

    由于数据比较少,可以先进行离散化来提高效率。 

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define INF 0x1f1f1f1f  
#define maxn 510005
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
int mi[maxn<<2];
int pos[maxn];
int res[maxn];
void update(int c,int l,int r,int rt)
{
    if(l==r)
    {
        mi[rt]=c;
        return;
    }
    int mid=(l+r)>>1;
    if(c<=mid)
        update(c,l,mid,rt<<1);
    else 
        update(c,mid+1,r,rt<<1|1);
    mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}
int ans;
void query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        ans=min(ans,mi[rt]);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)
        query(L,R,l,mid,rt<<1);
    if(R>mid)
        query(L,R,mid+1,r,rt<<1|1);
}
int main()
{
    int m,top,tmp,tt,ll,rr,x,i,ca=1,re;
    char op[2];
    while(scanf("%d",&m)!=EOF)
    {
        if(m==0)
            break;
        if(ca!=1)
            printf("\n");
        printf("Case %d:\n",ca++);
        memset(pos,-1,sizeof(pos));
        memset(mi,INF,sizeof(mi));
        top=0;
        while(m--)
        {
            scanf("%s%d",op,&x);
            if(op[0]=='B')
            {
                if(pos[x]==-1)
                {
                    pos[x]=top;
                    res[top++]=x;
                    update(x,1,maxn-1,1);
                }
            }
            else 
            {
                if(x<5000)
                {
                    ans=INF;
                    tmp=x;
                    for(i=top-1;i>=0;i--)
                    {
                        if(res[i]%x<tmp)
                        {
                            tmp=res[i]%x;
                            ans=res[i];
                        }
                        if(tmp==0)
                            break;
                    }
                    if(ans==INF)
                        printf("-1\n");
                    else printf("%d\n",pos[ans]+1);
                }
                else
                {
                    tt=500010/x;
                    re=INF;
                    tmp=x;
                    for(i=0;i<=tt;i++)
                    {
                        ans=INF;
                        ll=i*x;
                        ll=max(ll,1);
                        rr=(i+1)*x-1;
                        rr=min(rr,500009);
                        query(ll,rr,1,maxn-1,1);
                        if(ans==INF)
                            continue;
                        if(ans%x<tmp)
                        {
                            tmp=ans%x;
                            re=ans;
                        }
                        else if(ans%x==tmp)
                        {
                            if(pos[ans]>pos[re])
                                re=ans;
                        }
                    }
                    if(re==INF)
                        printf("-1\n");
                    else
                        printf("%d\n",pos[re]+1);
                }
            }
        }
    }
    return 0;
}

 

posted @ 2012-08-29 16:49  'wind  阅读(241)  评论(0编辑  收藏  举报