題目鏈接: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;
}