前言:
强烈谴责这套 ( exttt{div.2}) 的翻译(前面ABC更偏),做这套题目时想崩掉,还是读英文题面好。/cy
题意
可以参考参考神 ( exttt{Karry5307}) 的翻译,十分得清晰, 这里不多做赘述。
思路
其实思路十分显然,对于两颗木桩坐标为 (x_1) , (x_2)产生的总花费,分三种情况讨论:
-
显然左边的木桩左边的点全到左边的木桩,花费为 (x1-min_x) 。
-
显然右边的木桩右边的点全到右边的木桩,花费为 (max_x-x_2) 。
-
中间的点离哪棵木桩近就去哪,但是有一点十分重要,中间的木桩花费的最优情况肯定是分成两部分,左边到左边的木桩,右边到右边的木桩,令这两部分零界的点分别为 (x_3) , (x_4),产生的花费为 ((x_3-x_1)+(x_2-x_4)) 。
花费全加起来,你会恍然大悟地发现,花费为 ((max_x-min_x)-(x_3-x_2)) ( (x_2) 和 (x_3) 之间没有其它点)。
在每个状态下,(max_x) 和 (min_x) 是一定的,要让花费最小,问题就变成了动态维护区间中任意两点之间最远的距离。
题解区一群大佬用了蒟蒻我不会的科技轻松A掉了,于是蒟蒻我只好用大码量的线段树解决(vp时出现了一个小错误导致没有绝杀QwQ) 。
线段树维护三个值,区间内最长的两点间的距离,区间内最左边的点的位置,区间内最右边的点的位置。
你会发现顺便把动态维护最大值和最小值给做掉了,但是我原本还弄了个查询操作QwQ
具体的 (up) 操作请见代码
代码
(4.99s) 最优解第一
#include <bits/stdc++.h>
using namespace std;
#define ls n << 1
#define rs n << 1 | 1
const int N = 2e5;
inline int read()
{
register int s = 0;
register bool neg = 0;
register char c = getchar();
for (; c < '0' || c > '9'; c = getchar())
neg |= (c == '-');
for (; c >= '0' && c <= '9'; s = s * 10 + (c ^ 48), c = getchar())
;
return (neg ? -s : s);
}
int a,b,q[N+10],p[N+10],top;
bool t[N+10];
struct node {
int l,r,lmx,rmx,sum;
}s[N*4+10];
struct ask {
int opt,x;
}ask[N+10];
inline void up(int n) {
s[n].lmx=((s[ls].lmx==-1)?s[rs].lmx:s[ls].lmx);//区间内端点只有一个的时候将左端点和右端点赋值一样,方便操作。
s[n].rmx=((s[rs].rmx==-1)?s[ls].rmx:s[rs].rmx);
s[n].sum=max(max(s[ls].sum,s[rs].sum),s[ls].rmx!=-1&&s[rs].lmx!=-1?s[rs].lmx-s[ls].rmx:0);//注意左区间的右端点到有区间的左端点也要被统计在内
}
inline void build(int n,int l,int r) {
s[n].l=l;
s[n].r=r;
s[n].sum=0;
s[n].lmx=-1;
s[n].rmx=-1;
if(l==r) {
if(t[l]) s[n].lmx=s[n].rmx=p[l];
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(n);
}
inline void insert(int n,int k) {
if(s[n].l==s[n].r) {
s[n].lmx=s[n].rmx=p[k];
return;
}
int mid=(s[n].l+s[n].r)>>1;
if(k<=mid) insert(ls,k);
else insert(rs,k);
up(n);
}
inline void del(int n,int k) {
if(s[n].l==s[n].r) {
s[n].lmx=s[n].rmx=-1;
return;
}
int mid=(s[n].l+s[n].r)>>1;
if(k<=mid) del(ls,k);
else del(rs,k);
up(n);
}
signed main()
{
// freopen("in1.in","r",stdin);
a=read();
b=read();
top=0;
for(int i=1;i<=a;i++){
q[i]=p[++top]=read();
}
for(int i=1;i<=b;i++) {
ask[i].opt=read();
ask[i].x=p[++top]=read();
}
sort(p+1,p+top+1);
top=unique(p+1,p+top+1)-p-1;
for(int i=1;i<=a;i++) t[lower_bound(p+1,p+top+1,q[i])-p]=1;
build(1,1,top);
printf("%d
",s[1].rmx-s[1].lmx-s[1].sum);
for(int i=1;i<=b;i++) {
if(ask[i].opt==1)
insert(1,lower_bound(p+1,p+top+1,ask[i].x)-p);
else
del(1,lower_bound(p+1,p+top+1,ask[i].x)-p);
printf("%d
",s[1].rmx-s[1].lmx-s[1].sum);
}
return 0;
}
十分遗憾的一题QwQ