题解:P3992 [BJOI2017] 开车
不修改的情况下,有经典结论:在
但是这个结论很没前途,考虑转化为对边计算贡献(即将
考虑先把
我们需要计算每条边被经过了几次,不难发现,假设这条边是
定义一个新的数组
你会发现这个
我们需要动态维护这个
考虑对序列分块。我们对块内的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fr first
#define sc second
#define pii pair<int,int>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define ro(i,r,l) for(int i=r;i>=l;i--)
const int N=2e5+5;
int n,m,a[N],b[N],base[N],w[N],q;
struct Opt{
int x,k;
}qr[N];
int v[N];
#define lc(x) (x*val-val+1)
#define rc(x) min(x*val,m)
int val,bk[N],tag[N],ev[N];
ll sum[N],rs;
pair<int,ll>e[N];
void reset(int x){
rs-=sum[x],sum[x]=0;
fo(i,lc(x),rc(x)){
v[i]+=tag[x];
e[i]={v[i],w[i]};
sum[x]+=w[i]*abs(v[i]);
}
tag[x]=0,rs+=sum[x];
stable_sort(e+lc(x),e+rc(x)+1);
fo(i,lc(x)+1,rc(x))
e[i].sc+=e[i-1].sc;
fo(i,lc(x),rc(x))
ev[i]=e[i].fr;
}
void add(int l){
fo(i,l,rc(bk[l]))
v[i]++;
reset(bk[l]);
fo(i,bk[l]+1,(m-1)/val+1){
rs-=sum[i];
int t=lower_bound(ev+lc(i),ev+rc(i)+1,-tag[i])-ev;
if (t==lc(i))
sum[i]+=e[rc(i)].sc;
else sum[i]+=e[rc(i)].sc-e[t-1].sc*2;
tag[i]++,rs+=sum[i];
}
}
void del(int l){
fo(i,l,rc(bk[l]))
v[i]--;
reset(bk[l]);
fo(i,bk[l]+1,(m-1)/val+1){
rs-=sum[i];
int t=upper_bound(ev+lc(i),ev+rc(i)+1,-tag[i])-ev;
if (t==lc(i))
sum[i]-=e[rc(i)].sc;
else sum[i]-=e[rc(i)].sc-e[t-1].sc*2;
tag[i]--,rs+=sum[i];
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
fo(i,1,n){
cin>>a[i];
base[i]=a[i];
}
fo(i,1,n){
cin>>b[i];
base[n+i]=b[i];
}
cin>>q;
fo(i,1,q){
int x,k;
cin>>x>>k;
qr[i]={x,k};
base[n*2+i]=k;
}
sort(base+1,base+n*2+q+1);
m=unique(base+1,base+n*2+q+1)-base-1;
fo(i,1,m-1)
w[i]=base[i+1]-base[i];
fo(i,1,n){
a[i]=lower_bound(base+1,base+m+1,a[i])-base;
b[i]=lower_bound(base+1,base+m+1,b[i])-base;
v[a[i]]++,v[b[i]]--;
}
fo(i,1,q)
qr[i].k=lower_bound(base+1,base+m+1,qr[i].k)-base;
val=200;
fo(i,1,m){
bk[i]=(i-1)/val+1;
v[i]+=v[i-1];
}
fo(i,1,(m-1)/val+1)
reset(i);
cout<<rs<<'\n';
fo(i,1,q){
int x=qr[i].x,k=qr[i].k;
del(a[x]),add(k),a[x]=k;
cout<<rs<<'\n';
}
return 0;
}