题意
对于集合S,有两种操作:1、B X;2、A Y。B X代表将X加入集合S,并赋予X一个序号,代表它是第几个数;A Y代表从集合S中找出mod Y最小的数,输出的是该数的序号。
做法
非常厉害的一个题。
对 y 进行讨论,小的 y 每次加数的时候暴力更新,而大的 y 转换成 rmq 问题。
(这个我觉得是这题的难点,对于取模操作我很难去往看起来复杂度更高的 rmq 上面想。)
注意到这个 rmq 我们是可以离线的,而对于静态的问题是可以单调栈的(参考之前的 O(n)-O(1) RMQ),而只有加数操作,可以变成集合分裂,反过来就变成并查集。
const int N = int(4e4) + 9, M = int(5e5) + 9, SM = 1009;
char T[N]; int n, A[N], AA[N], P[M+1], id[M], nn;
VI res;
int Find(int x){
return P[x] == x ? x : P[x] = Find(P[x]);
}
void Union(int x, int y){
x = Find(x), y = Find(y);
assert(x != y);
P[x] = y;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
//cout << sqrt(M) << endl;
int __size__ = 256 << 20; // 256MB
char *__p__ = (char*)malloc(__size__) + __size__;
__asm__("movl %0, %%esp\n" :: "r"(__p__));
while(RD(n)){
printf("Case %d:\n", ++Case);
nn = 0; REP_1(i, M) P[i] = i;
RST(id); REP_1(i, n){
RC(T[i]); RD(A[i]);
if (T[i] == 'B') AA[++nn] = A[i], id[A[i]] = -nn;
}
FOR(i, 1, M){
if (!id[i]) Union(i, i+1);
}
CLR(res); DWN_1(i, n, 1) if (T[i] == 'B'){
Union(A[i], A[i]+1);
--nn;
}
else{
int r = A[i]; if (Find(1) == M){
res.PB(-1);
continue;
}
if (r < SM){
PII ar = MP(INF, 0);
DWN_1(t, nn, 1){
checkMin(ar, MP(AA[t]%r, -t));
if (!ar.fi) break;
}
res.PB(-ar.se);
continue;
}
PII a=MP(INF,0); int tt;
for(int it=Find(1);it!=M;it=Find(min(M, it+(r-tt)))){
checkMin(a, MP(tt=it%r, id[it]));
}
res.PB(-a.se);
}
RVS(res); ECH(it, res) OT(*it);
puts("");
}
}




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
