BZOJ4320 homework

Description:给定\(n\)个操作,向集合中加入一个数(保证每个数不同)或者查询集合内\(\text{%Y}\)的最小值

Solution:对于小于\(\sqrt{300000}\)的直接暴力,大于它的跳1,Y,Y的倍数,离Y最近的数,这个可以用并查集维护,离线好维护,我们直接离线,对于加点直接变成删点

写的时候级邪,要么是爆栈,要么是本地对拍没过不敢交,结果网上A了
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXX=3e5+10;
int g[550];
int f[MAXX];
int n,ans[MAXX];
bool vis[MAXX];
struct node
{
  int opt,val;
}t[MAXX];
inline int find(int x){
  if(f[x]==x)return x;
  else return f[x]=find(f[x]);
}
int main(){
   scanf("%d",&n);
   memset(ans,0x3f,sizeof(ans));
   memset(g,0x3f,sizeof(g));
   for(int i=1;i<=n;++i){
    char s[5];
    int val;
    scanf("%s%d",s,&val);
     t[i].val=val;
    if(s[0]=='A'){
      t[i].opt=0;
      vis[val]=1;
      for(int j=1;j<=549;++j)g[j]=min(g[j],val%j);
    }
    else {
      t[i].opt=1;
      if(t[i].val<=549)ans[i]=g[t[i].val];
    }
   }
   for(int i=1;i<=300000;++i){
    if(!vis[i])f[i]=i+1;
    else f[i]=i;
   }
   f[300001]=300001;
   for(int i=n;i>=1;i--){
    if(t[i].opt==0)f[t[i].val]=t[i].val+1;
    else {
      if(t[i].val>549){
        for(int j=0;j<=300000;j+=t[i].val){
          int x=find(max(j,1));
          if(x<=300000)ans[i]=min(ans[i],x%t[i].val);
         }
       }
     }
   }
   for(int i=1;i<=n;++i)if(t[i].opt==1)cout<<ans[i]<<endl;
   return 0;
}
posted @ 2018-09-04 20:55  ART_coder  阅读(115)  评论(0编辑  收藏  举报