题意:两种操作,一种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; }
时间: 2024-10-11 19:56:09