Description
Solution
发现a的访问很小,考虑从这入手,
把所有的数按a分成1000组,
对于每一组(设a全为x),首先,T每增加x,组里的每个数一定都会贡献+1,
但显然,有可能不用增加x那么多,有些数就已经有贡献了,如:a=5,b=1,当T=1的时候,它的贡献就从-1变成0 了,
发现这些数均是bmodb≤Tmodb,
那么这个用暴力维护即可,
复杂度:O(10002log(109)+1000m)
Code
#include <cstdio>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define NX(q) ((q)&(-(q)))
using namespace std;
typedef long long LL;
const int N=100500,M=1000;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans,mx;
int a[N],b[N],bv[N];
int f[M+5][M+5];
LL LW;
void change(int e,int q,int l2)
{
if(!q)return;
// for(;q<=e;q+=NX(q))f[e][q]+=l2;
fo(i,q,e)f[e][i]+=l2;
}
int find(int e,int q)
{
// int ans=0;for(;q>0;q-=NX(q))ans+=f[e][q];return ans;
return f[e][q];
}
LL JS(int T)
{
LL ans=0;
fo(i,1,mx)if(bv[i])
{
ans+=(LL)bv[i]*(LL)((T)/i);
ans+=(LL)find(i,T%i);
}
return ans;
}
int main()
{
freopen("calculate.in","r",stdin);
freopen("calculate.out","w",stdout);
int q,w,e,_;
for(read(_);_--;)
{
memset(f,0,sizeof(f));
fo(i,0,M)bv[i]=0;
LW=mx=0;
read(n),read(m);
fo(i,1,n)read(a[i]);
fo(i,1,n)
{
read(b[i]);mx=max(mx,a[i]);
change(a[i],b[i]%a[i],1);
bv[a[i]]++;
LW-=(LL)b[i]/a[i];
if(b[i]%a[i])LW--;
}
fo(i,1,m)
{
read(e),read(q);
if(e<3)
{
LW+=(LL)b[q]/a[q];bv[a[q]]--;
if(b[q]%a[q])LW++;
change(a[q],b[q]%a[q],-1);
if(e==1)read(a[q]);else read(b[q]);
mx=max(mx,a[q]);
LW-=(LL)b[q]/a[q];bv[a[q]]++;
if(b[q]%a[q])LW--;
change(a[q],b[q]%a[q],1);
}
else if(e==3)
{
int l=1,r=2e9;
while(l<r)
{
int mid=((LL)l+r)>>1;
if(LW+JS(mid)>=q)r=mid;
else l=mid+1;
}
printf("%d\n",l);
}
}
}
return 0;
}