BZOJ4320 Homework

mac2022-06-30  119

目录

BZOJ4320 Homework题解code

BZOJ4320 Homework

题目传送门

题解

看了题解之后发现是一个比较妙的分块+离线+并查集的做法。首先我们以30000为界,那么当询问\(\leq 30000\)的时候,我们就可以开个桶暴力进行查找。如果大于30000,那么我们就枚举30000以内\(x\)的倍数,然后通过并查集找出离这个倍数最近的比它大的值,就是答案。并查集维护的过程可以离线处理,将加点变成删点,每次删点就相当于两个联通块的合并。复杂度即为\(O(30000*n)\)

code

#include <bits/stdc++.h> using namespace std; typedef long long ll; bool Finish_read; template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x+'0');} template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');} template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);} /*================Header Template==============*/ const int maxn=5e5+500; const int inf=1e9+7; int n,M; char opt[2]; int x; struct query { int opt,x; }q[maxn]; int ans[maxn],mn[maxn],fa[maxn]; /*==================Define Area================*/ int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } int main() { read(n);M=sqrt(300000); memset(ans,-1,sizeof ans); memset(mn,0x3f,sizeof mn); for(int i=0;i<=300000;i++) fa[i]=i+1; fa[300001]=300001; for(int i=1;i<=n;i++) { scanf("%s",opt); read(x); if(opt[0]=='A') { q[i].opt=1;q[i].x=x; for(int j=1;j<=M;j++) mn[j]=min(mn[j],x%j); fa[x]=x; } else { q[i].opt=2,q[i].x=x; if(x<=M) ans[i]=mn[x]; } } for(int i=n;i;i--) { if(q[i].opt==2&&q[i].x>M) { int x=q[i].x; int res=inf; for(int j=0;j*x<300000;j++) { int tmp=find(j*x); if(tmp<=300000) res=min(res,tmp%x); } if(res==inf) res=x; ans[i]=res; } else if(q[i].opt==1) fa[q[i].x]=q[i].x+1; } for(int i=1;i<=n;i++) { if(~ans[i]) printf("%d\n",ans[i]); } return 0; }

转载于:https://www.cnblogs.com/Apocrypha/p/9432121.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)