【题解】 CF1732 D2
蒟蒻的第一篇题解
调了2h+的动态开点线段树被赛后10min写完的set瞎搞做法给吊打了
Description
维护一个集合
Solution
本来想写动态开点线段树维护,后来发现用 set 瞎搞就能解决。
对于一个修改操作
-
集合
S 就是题目中的集合。 -
集合
S1[k] 维护对于每个k ,k 的倍数中“可能”在集合S 中没出现的数的集合(就是有可能成为答案的集合)。 -
集合
S2[k] 维护每一个数的因子的集合。这里有一个小技巧,如果我们如果维护每个数的所有因子的话时间肯定会炸,但我们只要维护那些有可能询问到的因子就行了,一边询问一边维护S2 即可
具体地,对于插入操作,直接在
对于删除操作,先在
对于询问
还有一个细节,因为数据范围很大,所以要用
具体实现看代码吧 (其实还挺短的)
Code
#define int long long
int q;
set <int> S;//题目中的集合s
map <int,set<int> >disapr,factor;
//disapr维护对每个k,k的倍数中"可能"没出现过的数
//factor维护每个x的因数,一边修改一边维护,只记录有用的就行
signed main(){
cin>>q;
while(q--){
char opt;int x;
cin>>opt>>x;
if(opt=='+') S.insert(x);
else if(opt=='-'){
S.erase(x);
set <int> ::iterator it=factor[x].begin();
while(it!=factor[x].end()) disapr[*it].insert(x),it++;
}else{
disapr[x].insert(x);
int u=*disapr[x].begin();
factor[u].insert(x);
while(S.count(u)){
disapr[x].erase(u);
if(disapr[x].empty()) disapr[x].insert(u+x);
u=*disapr[x].begin(),factor[u].insert(x);
}
cout<<*disapr[x].begin()<<endl;
}
}
return 0;
}
暴力跳的复杂度本蒟蒻也不会算,可能是倒数之和均摊一下就变成