题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6274
题目大意:给出一个长度为n的数组a和数组b,定义函数。
接下来有m次操作,操作有如下三种:
1 x y :令 a[x] = y
2 x y :令b[x] = y
3 k : 找出最小的 t ,使其满足,并输出t。
题目思路:要解决这个题目,得抓住题目中给出的两个关键条件:
1、对于任意的 a[i] 均小于等于1000 ;2、操作3的数量小于等于1000。
对于原式子,我们可以令,,则原式子对于第i项可以化为,
,即。
当c1 >= c2 时,第 i 项的值为,
当c1 < c2 时,第i 项的值为。
所以。
由于是要求最小满足条件的 t ,我们自然可以考虑用二分来解决了。
由于 b[i] 的值和 a[i] 的值是固定的,所以我们可以通过预处理来求出的值,移项一下,就变成了求满足
的 t 了。
在二分check的时候,由于 t 已经是已知的了,那么也是固定的了,我们现在只需要考虑那些的情况,减掉这些情况就行了。
由于a[i]<=1000,我们就可以用数组 cnt[i][j] 表示a[x] == i 同时 b[x]%a[x] >= j的个数有多少个,cnt数组可以直接预处理处理。
这样对于每个,我们只用cnt数组就可以找出有多少个。再将这些情况减去即可。
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, int> pdi;
const int mod = 998244353;
const int MX = 1e5 + 7;
const int inf = 0x3f3f3f3f;
int n, m, T;
int a[MX], b[MX];
ll cnt[1005][1005];
bool check(ll t, ll x) {
ll res = 0;
for (int i = 1; i <= 1000; i++) {
res += t / i * cnt[i][0];
res -= cnt[i][t % i + 1];
}
return res >= x;
}
ll solve(ll x) {
ll l = 1, r = 1e13;
ll ans = 0;
while (l <= r) {
ll mid = (l + r) >> 1;
if (check(mid, x)) {
ans = mid;
r = mid - 1;
}
else l = mid + 1;
}
return ans;
}
int main() {
// FIN;
cin >> T;
while (T--) {
scanf("%d%d", &n, &m);
clr(cnt);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
ll res = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
res += b[i] / a[i];
cnt[a[i]][b[i] % a[i]]++;
}
for (int i = 1; i <= 1000; i++) {
for (int j = i - 1; j >= 0; j--)
cnt[i][j] += cnt[i][j + 1];
}
int op, x, y, k;
while (m--) {
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &x, &y);
for (int i = b[x] % a[x]; i >= 0; i--)
cnt[a[x]][i]--;
for (int i = b[x] % y; i >= 0; i--)
cnt[y][i]++;
res -= b[x] / a[x]; res += b[x] / y;
a[x] = y;
} else if (op == 2) {
scanf("%d%d", &x, &y);
for (int i = b[x] % a[x]; i >= 0; i--)
cnt[a[x]][i]--;
for (int i = y % a[x]; i >= 0; i--)
cnt[a[x]][i]++;
res -= b[x] / a[x]; res += y / a[x];
b[x] = y;
} else {
scanf("%d", &k);
printf("%lld\n", solve((ll)res + k));
}
}
}
return 0;
}