给出2个数列,{ai},{bi}.要求支持以下操作
- 修改数列a的第i个为x
 
- 修改数列b的第i个为x
 
- 给出k,求最小的t,满足∑⌊ait−bi⌋≥k
 
操作数不多于100000,操作3不多于1000;数列长度不多于10000,a的值域不大于1000。
 分析
将⌊ait−bi⌋拆开,观察前后可能出现的差。
⌊ait⌋−⌊aibi⌋
设t=k1ai+c1,bi=k2ai+c2,代入观察。
⌊ait−bi⌋=⌊ai(k1−k2)ai+c1−c2⌋
可以发现,当把式子拆开时,有2种情况。
- c1>c2,啥事没有。
 
- c1<c2,拆开后会多统计一个1。
 
事先统计{bi}模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; }
   |