首先对于家和公司在同一侧的预处理掉,这样就只剩家和公司不在同一侧的情况了。
if(K==1)ans=∑abs(x-pos)+abs(y-pos);注意到与x,y是否在两侧无关,所以用经典的中位数处理思想sort一遍取中位数贪心即可。
else{
一个人要走的距离是abs(x-pos)+abs(y-pos),让它最短话句话说就是让中点距pos尽可能近,于是我们将所有区间按中点排序,枚举从哪个重中点分成两块,左面走左面的桥右面走右面的桥,平衡树或者权值线段树动态维护中位数即可。
}
好久不写splay,练习了一发…>_<…
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
//by:MirrorGray
using namespace std;
const int N=211111,inf=0x3f3f3f3f;
struct node{
int x,y;
node(int a=0,int b=0){
x=a;y=b;
}
bool operator <(const node&b)const{
return x+y<b.x+b.y;
}
}a[N];
struct Splay{
int cnt,root;
struct splay{int l,r,fa,gs,size,d;ll sum;}sp[N];
void up(int tr){
sp[tr].size=sp[tr].gs;
sp[tr].sum=(ll)sp[tr].d*sp[tr].gs;
sp[tr].size+=sp[sp[tr].l].size+sp[sp[tr].r].size;
sp[tr].sum+=sp[sp[tr].l].sum+sp[sp[tr].r].sum;
}
Splay(){
cnt=2;root=1;
sp[1].d=-inf,sp[2].d=inf;
sp[1].r=2;sp[2].fa=1;
sp[1].gs=sp[2].gs=1;
up(2);up(1);
}
void zig(int tr){
int y=sp[tr].fa;
sp[y].l=sp[tr].r;
if(sp[tr].r)sp[sp[tr].r].fa=y;
sp[tr].fa=sp[y].fa;
if(sp[y].fa){
if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;
else sp[sp[y].fa].r=tr;
}
sp[y].fa=tr;sp[tr].r=y;
up(y);
}
void zag(int tr){
int y=sp[tr].fa;
sp[y].r=sp[tr].l;
if(sp[tr].l)sp[sp[tr].l].fa=y;
sp[tr].fa=sp[y].fa;
if(sp[y].fa){
if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;
else sp[sp[y].fa].r=tr;
}
sp[y].fa=tr;sp[tr].l=y;
up(y);
}
void splay(int tr,int aim){
while(sp[tr].fa!=aim){
int y=sp[tr].fa;
if(sp[y].fa==aim){
if(sp[y].l==tr)zig(tr);
else zag(tr);
}
else{
if(sp[sp[y].fa].l==y){
if(sp[y].l==tr)zig(y),zig(tr);
else zag(tr),zig(tr);
}
else{
if(sp[y].l==tr)zig(tr),zag(tr);
else zag(y),zag(tr);
}
}
}
up(tr);if(!aim)root=tr;
}
int pre(int tr,int d,int ret){
if(!tr)return ret;
if(sp[tr].d<d)return pre(sp[tr].r,d,tr);
else return pre(sp[tr].l,d,ret);
}
int nxt(int tr,int d,int ret){
if(!tr)return ret;
if(sp[tr].d>=d)return nxt(sp[tr].l,d,tr);
else return nxt(sp[tr].r,d,ret);
}
int kth(int tr,int k){
if(sp[sp[tr].l].size>=k)return kth(sp[tr].l,k);
if(sp[sp[tr].l].size+sp[tr].gs>=k)return tr;
return kth(sp[tr].r,k-(sp[sp[tr].l].size+sp[tr].gs));
}
void insert(int d){
int t1=pre(root,d,-1);splay(t1,0);
int t2=nxt(root,d,-1);splay(t2,t1);
if(sp[t2].d==d){
sp[t2].gs++;
up(t2);up(t1);
return ;
}
sp[t2].l=++cnt;
sp[cnt].d=d;sp[cnt].fa=t2;sp[cnt].gs=1;
up(cnt);up(t2);up(t1);
}
void del(int d){
int t1=pre(root,d,-1);splay(t1,0);
int t2=nxt(root,d+1,-1);splay(t2,t1);
int tr=sp[t2].l;
if(sp[tr].gs>1){
sp[tr].gs--;
up(tr);up(t2);up(t1);
return ;
}
sp[t2].l=0;
up(t2);up(t1);
}
ll Q(){
ll ret=0;
int tr=kth(root,sp[root].size>>1);
splay(tr,0);int l=sp[tr].l,r=sp[tr].r;
// cout<<"size : "<<sp[root].size<<" "<<sp[root].sum<<" "<<sp[root].d<<endl;
// cout<<sp[l].size<<" "<<sp[l].sum+inf<<endl;
// cout<<sp[r].size<<" "<<sp[r].sum-inf<<endl;
ret+=(ll)sp[l].size*sp[root].d-sp[l].sum;
ret+=sp[r].sum-(ll)sp[r].size*sp[root].d;
ret-=inf<<1;
return ret;
}
}t1,t2;
int main(){
int k,n;scanf("%d%d",&k,&n);
ll ans=0;int cnt=0;
for(int i=1;i<=n;i++){
char s1[2],s2[2];int b,c;
scanf("%s%d%s%d",s1,&b,s2,&c);
if(s1[0]==s2[0])ans+=abs(b-c);
else a[++cnt]=node(b,c),t2.insert(b),t2.insert(c);
}
ans+=cnt;
if(k==1)return printf("%lld\n",ans+t2.Q());
else{
sort(a+1,a+1+cnt);
ll tmp=t1.Q()+t2.Q();
for(int i=1;i<=cnt;i++){
t1.insert(a[i].x);t1.insert(a[i].y);
t2.del(a[i].x);t2.del(a[i].y);
tmp=min(tmp,t1.Q()+t2.Q());
}
printf("%lld\n",ans+tmp);
}
return 0;
}