给出2个数列,${a_i},{b_i}$.要求支持以下操作
- 修改数列a的第i个为x
- 修改数列b的第i个为x
- 给出k,求最小的t,满足$\sum \lfloor \frac {t-b_i}{a_i} \rfloor \ge k$
操作数不多于100000,操作3不多于1000;数列长度不多于10000,a的值域不大于1000。
分析
将$\lfloor \frac {t-b_i}{a_i} \rfloor$拆开,观察前后可能出现的差。
$$
\lfloor \frac {t}{a_i} \rfloor - \lfloor \frac {b_i}{a_i} \rfloor
$$
设$t=k_1a_i+c_1,b_i=k_2a_i+c_2$,代入观察。
$$
\begin{aligned}
\lfloor \frac {t-b_i}{a_i} \rfloor&=\lfloor \frac {(k_1-k_2)a_i+c_1-c_2}{a_i} \rfloor \\
\end{aligned}
$$
可以发现,当把式子拆开时,有2种情况。
- $c_1 > c_2$,啥事没有。
- $c_1 < c_2$,拆开后会多统计一个1。
事先统计${b_i}$模$a$的余数,那么有$t$后就能快速数出第2种情况的数量。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
using ll=long long;
const int MAXA=1010,MAXB=100010;
int nlen,mlen;
int a[MAXB],acnt[MAXA];
int b[MAXB];
int fts[MAXA][MAXA];
int pre[MAXA][MAXA];
void force(int i){
pre[i][0]=fts[i][0];
for(int j=1;j<MAXA;j++){
pre[i][j]=pre[i][j-1]+fts[i][j];
}
}
ll base=0;
bool check(ll k,ll t){
ll res=-base;
for(int i=1;i<=1000;i++){
res+=(t/i)*acnt[i];
int c=t%i;
ll offset=pre[i][1000]-pre[i][c];
res-=offset;
}
return res>=k;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int kase;cin>>kase;
while(kase--){
memset(acnt,0,sizeof(acnt));
memset(a,0,sizeof(a));
base=0;
memset(fts,0,sizeof(fts));
cin>>nlen>>mlen;
for(int i=1;i<=nlen;i++){
cin>>a[i];
acnt[a[i]]+=1;
}
for(int i=1;i<=nlen;i++){
cin>>b[i];
fts[a[i]][b[i]%a[i]]++;
base+=b[i]/a[i];
}
for(int i=1;i<=1000;i++){
force(i);
}
for(int i=1;i<=mlen;i++){
int opt;
cin>>opt;
if(opt==1){
int x,y;
cin>>x>>y;
acnt[a[x]]--;
fts[a[x]][b[x]%a[x]]--;
base-=b[x]/a[x];
force(a[x]);
a[x]=y;
fts[a[x]][b[x]%a[x]]++;
acnt[a[x]]++;
base+=b[x]/a[x];
force(a[x]);
}else if(opt==2){
int x,y;
cin>>x>>y;
fts[a[x]][b[x]%a[x]]--;
base-=b[x]/a[x];
force(a[x]);
b[x]=y;
fts[a[x]][b[x]%a[x]]++;
force(a[x]);
base+=b[x]/a[x];
}else if(opt==3){
int qk;cin>>qk;
ll l=0,r=1e13;
while(l+1<r){
ll mid=(l+r)/2;
if(check(qk,mid)){
r=mid;
}else l=mid+1;
}
for(ll i=l;i<=r;i++){
if(check(qk,i)){
cout<<i<<"\n";
break;
}
}
}
}
}
return 0;
}
|