[bzoj4320]Homework
对Y分块,对于Y<K,每一次1操作暴力修改这个Y的最大值,时间复杂度o(K);对于Y>K,维护一颗权值线段树并查询大于iK且离iK最近的数,时间复杂度o(6000000/K)(还有一个log),大约取K=2000左右(可以不用权值线段树而用并查集维护,复杂度较低)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define K 3000 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 #define ma 300000 8 int n,x,ans[ma],f[ma<<2]; 9 char s[11]; 10 void update(int k,int l,int r,int x){ 11 if (l==r){ 12 f[k]=l; 13 return; 14 } 15 if (x<=mid)update(L,l,mid,x); 16 else update(R,mid+1,r,x); 17 f[k]=min(f[L],f[R]); 18 } 19 int query(int k,int l,int r,int x,int y){ 20 if ((l>y)||(x>r))return 0x3f3f3f3f; 21 if ((x<=l)&&(r<=y))return f[k]; 22 return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 23 } 24 int main(){ 25 scanf("%d",&n); 26 memset(f,0x3f,sizeof(f)); 27 memset(ans,0x3f,sizeof(ans)); 28 for(int i=1;i<=n;i++){ 29 scanf("%s%d",s,&x); 30 if (s[0]=='A'){ 31 for(int j=1;j<=K;j++)ans[j]=min(ans[j],x%j); 32 update(1,1,ma,x); 33 continue; 34 } 35 if (x<=K){ 36 printf("%d\n",ans[x]); 37 continue; 38 } 39 ans[0]=x; 40 for(int j=0;j*x<=ma;j++)ans[0]=min(ans[0],query(1,1,ma,j*x,ma)-j*x); 41 printf("%d\n",ans[0]); 42 } 43 }