There are two sequences a1, a2, · · · , an, b1, b2, · · · , bn. Let S(t) =∑⌊(t−bi)ai⌋. . There are m operations
within three kinds as following:
• 1 x y: change value ax to y.
• 2 x y: change value bx to y.
• 3 k: ask min{t|k ≤ S(t)}
Input
The first line contains a integer T (1 ≤ T ≤ 5) representing the number of test cases.
For each test case, the first line contains two integers n (1 ≤ n ≤ 100000), m (1 ≤ m ≤ 10000).
The following line contains n integers representing the sequence a1, a2, · · · , an.
The following line contains n integers representing the sequence b1, b2, · · · , bn.
The following m lines, each line contains two or three integers representing an operation mentioned
above.
It is guaranteed that, at any time, we have 1 ≤ ai ≤ 1000, 1 ≤ bi
, k ≤ 109
. And the number of
queries (type 3 operation) in each test case will not exceed 1000.
Output
For each query operation (type 3 operation), print the answer in one line.
思路:我们发现,(t-b[i])/a[i],我们可以拆开,拆成t/a[i]-b[i]/a[i],然后t/a[i]和b[i]/a[i]也对应相减,因为是下取整,所以这样如果模数相减小于0,结果-1,否则不变.
而且发现a[i]最大为1000,这样我们可以做个桶把所有b[i]都存到对应的a[i]处,这样我们计算
t/a[i]-b[i]/a[i]就特别好算,我们怎么知道每一项模数相减是不是小于0呢,也就是怎么知道对应
a[i]∈[1,1000],t取每个值我们怎么知道有多少个b[i]%a[i]> t%a[i]呢? 树状数组不就可以了嘛!
维护1000个树状数组即可,这样每次查询的复杂度就是1000*log1000.
当然也可以预处理每个模数出现次数的前缀和,查询有多少模数比t%a[i]大时的复杂度就是O(1),
修改就是O(N),看起来好像不如树状数组,但是对于这道题目跑起来确实是快.
代码:
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5+5;
int n,m;
ll b[maxn],sumb[1234],a[maxn],num[1234];
int c[1234][1234];
int lowbit(int x)
{
return x&(-x);
}
void add(int pos,int x,int val)
{
x++;
for(int i = x;i<= 1000;i+= lowbit(i))
c[pos][i]+= val;
return ;
}
int get_sum(int pos,int x)
{
x++;
int ans = 0;
for(int i = 1000;i> 0;i-= lowbit(i))
ans+= c[pos][i];
for(int i = x;i> 0;i-= lowbit(i))
ans-= c[pos][i];
return ans;
}
bool judge(ll t,ll sum)
{
ll all = 0;
for(int i = 1;i<= 1000;i++)
{
all+= t/i*num[i]-sumb[i];
all-= get_sum(i,t%i);
}
return all>= sum;
}
void solve(ll sum)
{
ll l = 1,r = 1e14;
while(l<= r)
{
ll mid = (l+r)>>1;
if(judge(mid,sum))
r = mid-1;
else
l = mid+1;
}
printf("%lld\n",l);
}
int main()
{
int t;
cin>>t;
while(t--)
{
mem(sumb,0);
mem(num,0);
mem(c,0);
scanf("%d %d",&n,&m);
for(int i = 1;i<= n;i++)
scanf("%lld",&a[i]);
for(int i = 1;i<= n;i++)
{
scanf("%lld",&b[i]);
sumb[a[i]]+= b[i]/a[i];
add(a[i],b[i]%a[i],1);
num[a[i]]++;
}
while(m--)
{
ll o,x,y;
scanf("%lld %lld",&o,&x);
if(o == 1)
{
scanf("%lld",&y);
sumb[a[x]]-= b[x]/a[x];
add(a[x],b[x]%a[x],-1);
num[a[x]]--;
a[x] = y;
sumb[a[x]]+= b[x]/a[x];
add(a[x],b[x]%a[x],1);
num[a[x]]++;
}
else if(o == 2)
{
scanf("%lld",&y);
sumb[a[x]]-= b[x]/a[x];
add(a[x],b[x]%a[x],-1);
b[x] = y;
sumb[a[x]]+= b[x]/a[x];
add(a[x],b[x]%a[x],1);
}
else
{
solve(x);
}
}
}
return 0;
}