BZOJ 4320
阿新 • • 發佈:2020-08-26
\(bzoj4320~~Homework\)
\(1:\)在人物集合 S 中加入一個新的程式設計師,其代號為\(X\),保證\(X\)在當前集合中不存在。
\(2:\)在當前的人物集合中詢問程式設計師的\(mod~Y\) 最小的值。 (為什麼統計這個?因為拯救
過世界的人太多了,只能取模)
其中 對於 100%的資料:\(N≤100000, 1≤X,Y≤300000,\)保證第二行為操作 1。
好神的題:根號分治+並查集
設\(N\)表示\(x\)的最大值,考慮對權值序列分治,當模數不超\(\sqrt N\),開\(\sqrt N\)個桶,每次暴力更新桶,\(O(1)\)求答案
當模數超過\(\sqrt N\)時,它在\(n\)
#include<bits/stdc++.h> using namespace std; int n,siz,m,q[100010],f[300001]; int ans[100010],st[610]; bool vis[300010]; char str[10]; int find(int x){return f[x] == x ? x : f[x] = find(f[x]);} int main(){ scanf("%d",&n); siz = 550; int i,j; memset(st,0x3f,sizeof(st)); for(i = 1;i <= n;++i){ scanf("%s%d",str,&q[i]); if(str[0] == 'A'){ for(int j = 1;j <= siz;++j) st[j] = min(st[j],q[i] % j); m = max(m,q[i]),vis[q[i]] = 1,q[i] = -q[i]; } else if(q[i] <= siz) ans[i] = st[q[i]]; } for(i = 0;i <= m+1;++i) f[i] = (vis[i]) ? i : i+1; for(i = n;i >= 1;--i){ if(q[i] < 0) f[-q[i]] = find(-q[i]+1); else{ if(q[i]>siz){ ans[i]=1 << 30; for(j = 0;j <= m;j += q[i]) ans[i]=min(ans[i],find(j)%q[i]); } } } for(i=1;i<=n;i++) if(q[i]>0) printf("%d\n",ans[i]); }