- 一道神题,对拍狂该了两个小时,终于过了,常数还巨大
- 首先答案最优肯定是车和加油站都排好须一一对应,现在我们将所有的有用坐标离散化,考虑维护每一段距离对答案的贡献
- 我们发现,如果把车设成1,加油站设成-1,放在其所在的位置上,累一遍前缀和,那么每个位置上的数值就是现在失配的车或加油站,那么贡献为其绝对值乘上那段区间的距离。
- 我们考虑分块维护贡献,对每个块对其按前缀和排序,这样可以将绝对值去掉,改动车的位置实际上就是把原来地方减一,将新的地方加一
- 对于边角我们暴力修改并重构该块,重新计算贡献,对于完整的块我们打上lazy标记,计算式二分零点位置计算贡献即可
#include<bits/stdc++.h>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=5e4+5;
template<typename T>bool cmax(T &a,T b){return (a<b)?a=b,1:0;}
template<typename T>bool cmin(T &a,T b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
T ans=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
return ans*f;
}
template<typename T>void write(T x,char y)
{
if(x==0)
{
putchar('0');putchar(y);
return;
}
if(x<0)
{
putchar('-');
x=-x;
}
static char wr[20];
int top=0;
for(;x;x/=10)wr[++top]=x%10+'0';
while(top)putchar(wr[top--]);
putchar(y);
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("4908.in","r",stdin);
freopen("4908.out","w",stdout);
#endif
}
int n,m;
int a[N],b[N],q[N*3],tot;
int car[N],pos[N];
void input()
{
n=read<int>();
For(i,1,n)a[i]=q[++tot]=read<int>();
For(i,1,n)b[i]=q[++tot]=read<int>();
m=read<int>();
For(i,1,m)car[i]=read<int>(),pos[i]=q[++tot]=read<int>();
}
#define find(x) lower_bound(q+1,q+tot+1,x)-q
int ac_pos[N*3];
ll sum[N*3],dis[N*3];
int block,st[400],ed[400],lazy[400],tim,blcok;
ll val[400],num[400][400];
ll ans;
struct node
{
ll sum,dis,id;
bool operator < (const node &s)const
{return sum<s.sum;}
}e[N*3];
ll w[400][400];
void rebuild(int id)
{
// cout<<"build"<<' '<<id<<endl;
// For(i,st[id],ed[id])cout<<e[i].sum<<' '<<e[i].dis<<endl;
// puts("");
ans-=val[id];val[id]=0;
For(i,st[id],ed[id])e[i].sum+=lazy[id];
lazy[id]=0;
sort(e+st[id],e+ed[id]+1);
For(i,st[id],ed[id])
{
ac_pos[e[i].id]=i;
num[id][i-st[id]+1]=num[id][i-st[id]]+e[i].dis*e[i].sum;
w[id][i-st[id]+1]=w[id][i-st[id]]+e[i].dis;
// cout<<e[i].sum<<' '<<e[i].dis<<endl;
val[id]+=abs(e[i].sum)*e[i].dis;
}
ans+=val[id];
//puts("");
}
void recal(int id)
{
//if(!lazy[id])return;
//cout<<"id"<<' '<<id<<endl;
//cout<<"val"<<' '<<val[id]<<endl;
//cout<<"lazy"<<' '<<lazy[id]<<endl;
//For(i,st[id],ed[id])cout<<e[i].sum<<' '<<e[i].dis<<endl;
ans-=val[id];val[id]=0;
node temp={-lazy[id],0};
int p;
p=lower_bound(e+st[id],e+ed[id]+1,temp)-e-st[id];
//cout<<"p"<<' '<<p<<endl;
//cout<<"num"<<' '<<num[id][p]<<endl;
val[id]+=abs((num[id][p])+w[id][p]*lazy[id]);
temp={-lazy[id]+1,0};
p=lower_bound(e+st[id],e+ed[id]+1,temp)-e-st[id];
//cout<<"p"<<' '<<p<<endl;
val[id]+=abs((num[id][ed[id]-st[id]+1]-num[id][p])+lazy[id]*(w[id][ed[id]-st[id]+1]-w[id][p]));
ans+=val[id];
//cout<<"val"<<' '<<val[id]<<endl;
//puts("");
}
int bl[N*3];
void init()
{
sort(q+1,q+tot+1);
tot=unique(q+1,q+tot+1)-q-1;
For(i,1,n)a[i]=find(a[i]),++sum[a[i]];
For(i,1,n)b[i]=find(b[i]),--sum[b[i]];
/*For(i,1,n)cout<<a[i]<<' ';
cout<<endl;
For(i,1,n)cout<<b[i]<<' ';
cot<<endl;*/
For(i,1,m)pos[i]=find(pos[i]);
For(i,1,tot)sum[i]+=sum[i-1];
//For(i,1,tot)cout<<sum[i]<<endl;
For(i,1,tot-1)dis[i]=q[i+1]-q[i];
tim=sqrt(tot);
if(tim==1)++tim;
For(i,1,tot)
{
if(i%tim==1)st[++block]=i;
if(i%tim==0||i==tot)ed[block]=i;
bl[i]=block;
e[i]=(node){sum[i],dis[i],i};
//cout<<e[i].sum<<' '<<e[i].dis<<endl;
}
For(i,1,block)rebuild(i);
// For(i,1,tot)cout<<e[i].sum<<' '<<e[i].dis<<endl;
// puts("");
//For(i,1,tot)cout<<i<<' '<<e[i].sum<<' '<<e[i].dis<<endl;
}
void update(int p,int v)
{
For(i,bl[p],block)
{
if(st[i]<p)
{
For(j,p,ed[i])e[ac_pos[j]].sum+=v;
rebuild(i);
}
else
{
lazy[i]+=v;
recal(i);
}
}
}
void work()
{
write(ans,'\n');
For(i,1,m)
{
update(a[car[i]],-1);
a[car[i]]=pos[i];
update(a[car[i]],1);
write(ans,'\n');
}
}
int main()
{
file();
input();
init();
work();
return 0;
}