- 思路:每一次,对于每个 mi ,若其不是 mi
中的最小值,则只留 mi 人,其他人迁至 min(mi) 处。可以知道这是不劣的。
- 然后,特判min(mi)=1 and −1的情况;若没有,则模拟题意,不超过O(nlogn)
我像个傻子一样写了个线段树,见谅
die 码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
struct node{
ll l,r,mn,sum,msum;
}t[10000007];
int a[10000007],m[10000007];
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].sum=a[l],t[p].mn=t[p].msum=m[l];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].msum=t[p*2].msum+t[p*2+1].msum;
t[p].mn=min(t[p*2].mn,t[p*2+1].mn);
}
void changea(int p,int x,int v){
if(t[p].l==t[p].r&&t[p].l==x){
a[t[p].l]=v;
t[p].sum=a[t[p].l],t[p].mn=t[p].msum=m[t[p].l];
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(x<=mid){
changea(p*2,x,v);
}else{
changea(p*2+1,x,v);
}
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].msum=t[p*2].msum+t[p*2+1].msum;
t[p].mn=min(t[p*2].mn,t[p*2+1].mn);
}
void changem(int p,int x,int v){
if(t[p].l==t[p].r&&t[p].l==x){
m[t[p].l]=v;
t[p].sum=a[t[p].l],t[p].mn=t[p].msum=m[t[p].l];
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(x<=mid){
changem(p*2,x,v);
}else{
changem(p*2+1,x,v);
}
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].msum=t[p*2].msum+t[p*2+1].msum;
t[p].mn=min(t[p*2].mn,t[p*2+1].mn);
}
ll askmn(int p,int l,int r){
if(l<=t[p].l&&r>=t[p].r){
return t[p].mn;
}
int mid=(t[p].l+t[p].r)>>1;
ll v=0;
if(l<=mid){
v=min(v,askmn(p*2,l,r));
}
if(r>mid){
v=min(v,askmn(p*2+1,l,r));
}
return v;
}
ll asksum(int p,int l,int r){
if(l<=t[p].l&&r>=t[p].r){
return t[p].sum;
}
int mid=(t[p].l+t[p].r)>>1;
ll sum=0;
if(l<=mid){
sum+=asksum(p*2,l,r);
}
if(r>mid){
sum+=asksum(p*2+1,l,r);
}
return sum;
}
ll askmsum(int p,int l,int r){
if(l<=t[p].l&&r>=t[p].r){
return t[p].msum;
}
int mid=(t[p].l+t[p].r)>>1;
ll sum=0;
if(l<=mid){
sum+=askmsum(p*2,l,r);
}
if(r>mid){
sum+=askmsum(p*2+1,l,r);
}
return sum;
}
signed main(){
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%lld",&m[i]);
}
build(1,1,n);
while(q--){
int op,x,y;scanf("%d",&op);
if(op==1){
scanf("%lld%lld",&x,&y);
changea(1,x,y);
}else if(op==2){
scanf("%lld%lld",&x,&y);
changem(1,x,y);
}else{
ll sa=asksum(1,1,n);
ll sm=askmsum(1,1,n);
if(sa<sm){
printf("0\n");continue;
}
ll smn=askmn(1,1,n);
ll jian=(sm-smn-(n-1));
if(!jian){
printf("-1\n");continue;
}
if(smn==1){
printf("%lld\n",(sa/jian));continue;
}
int tot=0;
while(sa>=sm){
sa-=jian;sa/=smn;tot++;
}
printf("%lld\n",tot);
}
}
return 0;
}