题解:P7603 [THUPC2021] 鬼街
折半报警器。第一次看到这个玩意应该是在 gym 102331F。
设
考虑减少判断次数,引入折半报警器。上述条件等价于
不难发现,每次报警时,一个监视器的
堆的删除可以使用懒惰删除,维护每个监视器的最新阈值编号、以及堆中每个阈值信息的编号即可。
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define mp make_pair
#define sec second
#define fir first
#define pii pair<int,int>
#define lowbit(i) i&-i
#define int long long
#define qingbai 666
using namespace std;
typedef long long ll;
const int N=1e5+5,M=105,inf=1e9+7,mo=998244353;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int n,m;
vector<int>d[N];
struct node{
int id,opid,targ;//监视器编号、阈值编号及报警阈值
friend bool operator<(node x,node y){
return x.targ>y.targ;
}
};
priority_queue<node>q[N];
int cnt[N];
pii mon[N];
int stp[N],nop[N];
bool vis[N];
int gets(int x){
int res=0;
for(auto j:d[mon[x].fir])
res+=cnt[j];
return res;
}
signed main(){
read(n),read(m);
rep(i,1,n){
int x=i;
rep(j,2,sqrt(i)){
int cnt=0;
while(x%j==0)
x/=j,cnt++;
if(cnt!=0)d[i].push_back(j);
}
if(x!=1)d[i].push_back(x);
}
int lans=0,cntm=0;
vector<int>ans;
while(m--){
int op,x,y;
read(op),read(x),read(y),y^=lans;
if(op==1){
cntm++;
if(!y){
ans.push_back(cntm);
continue;
}
int targ=(y-1)/d[x].size()+1;
nop[cntm]++;
for(auto i:d[x])
q[i].push((node){cntm,nop[cntm],targ+cnt[i]}),stp[cntm]+=cnt[i];
mon[cntm]=mp(x,y+stp[cntm]);
}
else{
for(auto i:d[x])
cnt[i]+=y;
for(auto i:d[x]){
while(!q[i].empty()&&q[i].top().targ<=cnt[i]){
node nw=q[i].top();
q[i].pop();
if(vis[nw.id])continue;
if(nop[nw.id]!=nw.opid)continue;//懒惰删除
int nws=gets(nw.id);
if(nws>=mon[nw.id].sec)vis[nw.id]=1,ans.push_back(nw.id);
else{
int ntg=(mon[nw.id].sec-nws-1)/d[mon[nw.id].fir].size()+1;
nop[nw.id]++;
for(auto j:d[mon[nw.id].fir])
q[j].push((node){nw.id,nop[nw.id],cnt[j]+ntg});
}
}
}
printf("%lld",(int)ans.size());
sort(ans.begin(),ans.end());
for(auto i:ans)
printf(" %lld",i);
lans=ans.size();
ans.clear();
puts("");
}
}
return 0;
}