题意:两种操作,一种B t向集合中插入元素t,另一种A t,查询集合中模y最小的数,如果有多个最小则取最后插入的那个。操作数<=40000,1 ≤ t≤ 500 000,1 ≤ y ≤ 1 000 000.
解法:每个数都插入等于其坐标的位置。线段树维护区间最小值,然后每次询问都查询[0,y-1],[y-1,2*y-1]....各循环节区间的最小值然后分别松弛答案。当y过小的时候,复杂度会退化,可以完全暴力枚举,这个复杂度和数据有关系。
代码:
/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef unsigned long long LL;
const int Max=500110;
const int INF=1e9+7;
int tool[Max*10];
struct point
{
int value;
int time;
};
bool operator<(const point& a,const point& b)
{
if(a.value!=b.value)
return a.value<b.value;
return a.time>b.time;
}
struct node
{
int l,r;
node *pl,*pr;
point thing;
} nodes[2*Max];
int tot=0;
void buildtree(node *p,int left,int right)
{
p->l=left;
p->r=right;
p->thing.value=INF;
if(left==right)
{
return ;
}
int middle=(left+right)/2;
tot++;
p->pl=nodes+tot;
buildtree(p->pl,left,middle);
tot++;
p->pr=nodes+tot;
buildtree(p->pr,middle+1,right);
}
point query(node* p,int left,int right)
{
if(p->l==left&&p->r==right)
return p->thing;
int middle=(p->l+p->r)/2;
if(right<=middle)
return query(p->pl,left,right);
if(left>middle)
return query(p->pr,left,right);
return min(query(p->pl,left,middle),query(p->pr,middle+1,right));
}
void update(node* p,int pos,int time)
{
// cout<<p->l<<" "<<p->r<<" "<<pos<<endl;
if(p->l==pos&&p->r==pos)
{
p->thing.value=pos;
p->thing.time=time;
return ;
}
int middle=(p->l+p->r)/2;
if(pos>middle)
update(p->pr,pos,time);
else
update(p->pl,pos,time);
p->thing=min(p->pl->thing,p->pr->thing);
}
int n;
int ma=0;
int time=1;
void solve(int t)
{
if(t<=20000)
{
int ans=t;
int out=0;
for(int i=time-1;i>=1;i--)
{
// cout<<" "<<time<<endl;
if(tool[i]%t<ans)
{
ans=tool[i]%t;
out=i;//cout<<" "<<time<<" "<<i<<endl;
}
if(ans==0)
break;
}
if(ans==t)
puts("-1");
else
printf("%d\n",out);
return;
}
point p;
p.time=INF;
p.value=t;
point tool;
for(int i=0; i<ma/t; i++)
{
tool=query(nodes,t*i,t*i+t-1);
if(tool.value>=INF)
continue;
tool.value%=t;
p=min(p,tool);
}
tool=query(nodes,t*(ma/t),t*(ma/t)+ma%t);
if(tool.value<INF)
{
tool.value%=t;
p=min(p,tool);
}
if(p.value==t)
puts("-1");
else
printf("%d\n",p.time);
}
int main()
{
int kk=1;
while(scanf("%d",&n)==1&&n)
{
time=1;
ma=0;
printf("Case %d:\n",kk++);
tot=0;
buildtree(nodes,0,Max-10);
while(n--)
{
char c;int t;
getchar();
scanf("%c%d",&c,&t);
if(c=='B')
{
update(nodes,t,time);
tool[time++]=t;
ma=max(ma,t);
}
else
solve(t);
}
printf("\n");
}
return 0;
}