题意:

题解:
我们要先将问题转换
圈是车,x是加油站。红色部分为车移动的路线
数组a是车数量的前缀和
数组b是加油站的前缀和
而a[i]与b[i]的差的绝对值就是对应的红色路被走的次数
现在车发生位置移动,b数组没有影响,a数组i到j这段整体减一
现在我们要做的就是维护a序列,支持区间+1/-1,询问∑| a[i] - b[i] |
线段树不能实现
用分块实现
实现过程:
按照下标分块,每块按照a[i] - b[i] 排序
代码:
代码为借鉴
#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 150005
#define MAXB 2005
using namespace std;
typedef long long ll;
int N,B,Q;
int a[MAXN], w[MAXN];
map<int,int> mp;
map<int,int>::iterator it;
map<int,int> id;
int q[MAXN][2];
struct Node{
int w,val,id,sw;
Node(int id=0, ll val=0, int w=0):id(id), val(val), w(w){}
bool operator < (const Node& n1) const{
return val < n1.val;
}
};
vector<Node> adj[MAXN];
ll ANS = 0, ans[MAXN], base[MAXN];
void rebuild(int id){
ANS -= ans[id]; ans[id] = 0;
sort(adj[id].begin(), adj[id].end());
for(int k=0;k<adj[id].size();k++){
ans[id] += abs((ll)adj[id][k].val + base[id]) * adj[id][k].w;
if(k==0) adj[id][k].sw = adj[id][k].w;
else adj[id][k].sw = adj[id][k-1].sw + adj[id][k].w;
}
ANS += ans[id];
}
void work(int l, int r, int f){
int idl = l/B, idr = r/B;
if(idl==idr){
for(int k=0;k<adj[idl].size();k++){
if(l<=adj[idl][k].id && adj[idl][k].id<=r){
if(f==0) adj[idl][k].val -= 1;
if(f==1) adj[idl][k].val += 1;
}
}
rebuild(idl);
}
else{
if(idl+1<idr){
for(int id=idl+1;id<idr;id++){
//
int lb = 0, rb = adj[id].size()-1, mid;
if(f==0){
if(adj[id][rb].val + base[id] <= 0){
ans[id] += adj[id][rb].sw;
ANS += adj[id][rb].sw;
base[id] -= 1;
continue;
}
while(lb < rb){
mid = (lb + rb)/2;
if(adj[id][mid].val + base[id] > 0) rb = mid;
else lb = mid + 1;
}
base[id] -= 1;
int p = rb;
if(p==0){
ans[id] -= adj[id][adj[id].size()-1].sw;
ANS -= adj[id][adj[id].size()-1].sw;
}
else{
ans[id] += adj[id][p-1].sw;
ANS += adj[id][p-1].sw;
ans[id] -= adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;
ANS -= adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;
}
}
else{
if(adj[id][rb].val + base[id] < 0){
ans[id] -= adj[id][rb].sw;
ANS -= adj[id][rb].sw;
base[id] += 1;
continue;
}
while(lb < rb){
mid = (lb + rb)/2;
if(adj[id][mid].val + base[id] >= 0) rb = mid;
else lb = mid + 1;
}
base[id] += 1;
int p = rb;
if(p==0){
ans[id] += adj[id][adj[id].size()-1].sw;
ANS += adj[id][adj[id].size()-1].sw;
}
else{
ans[id] -= adj[id][p-1].sw;
ANS -= adj[id][p-1].sw;
ans[id] += adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;
ANS += adj[id][adj[id].size()-1].sw - adj[id][p-1].sw;
}
}
}
}
for(int k=0;k<adj[idl].size();k++){
if(l<=adj[idl][k].id && adj[idl][k].id<=r){
if(f==0) adj[idl][k].val -= 1;
if(f==1) adj[idl][k].val += 1;
}
}
rebuild(idl);
for(int k=0;k<adj[idr].size();k++){
if(l<=adj[idr][k].id && adj[idr][k].id<=r){
if(f==0) adj[idr][k].val -= 1;
if(f==1) adj[idr][k].val += 1;
}
}
rebuild(idr);
}
}
int pos[MAXN];
int main(){
scanf("%d", &N);
int x;
for(int i=1;i<=N;i++){
scanf("%d", &x);
pos[i] = x;
mp[x] += 1;
}
for(int i=1;i<=N;i++){
scanf("%d", &x);
mp[x] -= 1;
}
scanf("%d", &Q);
for(int i=1;i<=Q;i++){
scanf("%d%d", &q[i][0], &q[i][1]);
if(mp.count(q[i][1])==0) mp[q[i][1]] = 0;
}
int n = 0, x0 = 0;
for(it=mp.begin(); it!=mp.end(); ++it){
x = it->first;
id[x] = ++n;
w[n-1] = x - x0;
a[n] = a[n-1] + it->second;
x0 = x;
}
N = n; B = sqrt(N);
//cerr<<"B = "<<B<<endl;
for(int i=1;i<=N;i++){
adj[i/B].push_back(Node(i,a[i],w[i]));
}
for(int id=0;id<=N/B;++id){
rebuild(id);
}
printf("%lld\n", ANS);
int l,r;
for(int i=1;i<=Q;i++){
l = id[pos[q[i][0]]];
r = id[q[i][1]];
pos[q[i][0]] = q[i][1];
//cerr<<"work "<<l<<" "<<r<<endl;
if(l < r) work(l, r-1, 0);
if(l > r) work(r, l-1, 1);
printf("%lld\n", ANS);
}
return 0;
} 
京公网安备 11010502036488号