在河同一边的可以不理他
问题就是有若干个人在A侧l位置,要通过桥到B侧r位置 l< r
当K=1时发现答案就是所有l,r的中位数
因为
ans=|p−l|+|p−r|
(好有道理我怎么没发现qwq)
同时这启示我们(观察易得??qwq)当有两个桥时,每个人会选择更接近(l,r)中点的桥
所以我们将(l,r)按照中点排序后,两个桥将这些人分成了两部分,我们枚举这个分界线i,用主席树找中位数并统计其贡献
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;
const int maxn = 210000;
int kn,n,m;
int t[maxn<<1],tp,To[maxn<<1],K;
map<int,int>mt;
struct node{int l,r,mid;}a[maxn];
inline bool cmp(const node x,const node y){return x.mid<y.mid;}
struct segment{int num; ll sum;}seg[maxn<<2];
ll f[maxn],g[maxn];
void clear(const int x,const int l,const int r)
{
seg[x].num=0,seg[x].sum=0;
if(l==r) return;
int mid=l+r>>1;
clear(x<<1,l,mid); clear(x<<1|1,mid+1,r);
}
int loc;
void upd(const int x,const int l,const int r)
{
seg[x].num++; seg[x].sum+=To[loc];
if(l==r) return;
int mid=l+r>>1;
if(loc<=mid) upd(x<<1,l,mid);
else upd(x<<1|1,mid+1,r);
}
int fd(const int x,const int l,const int r,int k)
{
if(l==r) return l;
int mid=l+r>>1,lc=x<<1;
if(seg[lc].num<k) return fd(x<<1|1,mid+1,r,k-seg[lc].num);
else return fd(x<<1,l,mid,k);
}
int q1(const int x,const int l,const int r)
{
if(l>loc) return 0;
if(r<=loc) return seg[x].num;
int mid=l+r>>1;
return q1(x<<1,l,mid)+q1(x<<1|1,mid+1,r);
}
ll q2(const int x,const int l,const int r)
{
if(l>loc) return 0;
if(r<=loc) return seg[x].sum;
int mid=l+r>>1;
return q2(x<<1,l,mid)+q2(x<<1|1,mid+1,r);
}
ll re,ans;
char s1[10],s2[10];
int main()
{
scanf("%d%d",&kn,&n);
for(int i=1;i<=n;i++)
{
int l,r;
scanf("%s%d",s1,&l);
scanf("%s%d",s2,&r);
if(s1[0]==s2[0]) { ans+=abs(l-r);continue; }
if(l>r) swap(l,r);
a[++m]=(node){l,r,l+r};
t[++tp]=l,t[++tp]=r;
}
sort(t+1,t+tp+1); t[0]=t[1]-1; K=0;
for(int i=1;i<=tp;i++)
if(t[i]!=t[i-1]) To[mt[t[i]]=++K]=t[i];
for(int i=1;i<=m;i++) a[i].l=mt[a[i].l],a[i].r=mt[a[i].r];
sort(a+1,a+m+1,cmp);
ans+=m;
if(!m) return printf("%lld\n",ans),0;
ll temp=0;
for(int i=1;i<=m;i++)
{
loc=a[i].l; upd(1,1,K);
loc=a[i].r; upd(1,1,K);
temp+=a[i].mid;
loc=fd(1,1,K,i);
ll c1=q1(1,1,K),c2=q2(1,1,K);
f[i]=c1*To[loc]-c2+temp-c2-(i*2ll-c1)*To[loc];
}
if(kn==1) return printf("%lld\n",f[m]+ans),0;
clear(1,1,K); temp=0;
for(int i=m;i>=1;i--)
{
loc=a[i].l; upd(1,1,K);
loc=a[i].r; upd(1,1,K);
temp+=a[i].mid;
loc=fd(1,1,K,(m-i+1));
ll c1=q1(1,1,K),c2=q2(1,1,K);
g[i]=c1*To[loc]-c2+temp-c2-((m-i+1)*2ll-c1)*To[loc];
}
re=LLONG_MAX;
for(int i=1;i<=m;i++) re=min(re,f[i-1]+g[i]);
printf("%lld\n",re+ans);
return 0;
}