按a的值分组,处理一下余数,二分一下就可以了
但是我二分上界设置的1e18,在计算过程中爆炸了,正确的上界应该是1e14
真的调了很久才意识到这个问题。。。
明天就打区域赛了。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1010;
const int maxm = 1e5 + 10;
const long long INF = 1e14;
int T, N, M;
ll a[100005], b[100005];
ll cnt, num[maxn][maxn];
bool judge(ll x, ll K) {
ll ans = 0;
for (int i = 1; i <= 1000; i++) {
ans += x/i*num[i][0]-num[i][x%i+1];
}
return (ans >= K);
}
ll solve(ll K) {
ll l = 0, r = INF, mid;
while (l <= r) {
mid = (l + r)>>1;
if (judge(mid, K)) r = mid - 1;
else l = mid + 1;
}
return l;
}
int main() {
scanf("%d", &T);
while (T--) {
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]);
cnt = 0;
memset(num, 0, sizeof(num));
for (int i = 1; i <= N; i++) {
cnt += b[i]/a[i];
num[a[i]][b[i]%a[i]]++;
}
for (int i = 1; i <= 1000; i++) {
for (int j = i-1; j >= 0; j--) {
num[i][j] += num[i][j+1];
}
}
int op, x, y, k;
while (M--) {
scanf("%d", &op);
if (op == 1) {
scanf("%d %d", &x, &y);
cnt -= b[x]/a[x];
for (int j = b[x]%a[x]; j >= 0; j--) num[a[x]][j]--;
a[x] = y;
cnt += b[x]/a[x];
for (int j = b[x]%a[x]; j >= 0; j--) num[a[x]][j]++;
}
else if (op == 2) {
scanf("%d %d", &x, &y);
cnt -= b[x]/a[x];
for (int j = b[x]%a[x]; j >= 0; j--) num[a[x]][j]--;
b[x] = y;
cnt += b[x]/a[x];
for (int j = b[x]%a[x]; j >= 0; j--) num[a[x]][j]++;
}
else {
scanf("%d", &k);
printf("%lld\n", solve(cnt+k));
}
}
}
return 0;
}