Description
一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B。
每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000。相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度。区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对。
城市中有 N 个居民。第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上。一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过 K 座横跨河流的大桥。
由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。当政府建造最多 K 座桥之后,设 Di 表示第 i 个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得 D1+D2+⋯+DN 最小。
Input
输入的第一行包含两个正整数 K 和 N,分别表示桥的上限数量和居民的数量。
接下来 N 行,每一行包含四个参数:Pi,Si,Qi 和 Ti,表示第 i 个居民的房子在区域 Pi 的 Si 号建筑上,且他的办公室位于 Qi 区域的 Ti 号建筑上。
Output
输出仅为一行,包含一个整数,表示 D1+D2+⋯+DN 的最小值。
Sample Input
1 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7
Sample Output
24
HINT
子任务
所有数据都保证:Pi 和 Qi 为字符 “A” 和 “B” 中的一个, 0≤Si,Ti≤1000000000,同一栋建筑内可能有超过 1 间房子或办公室(或二者的组合,即房子或办公室的数量同时大于等于 1)。
子任务 1 (8 分)
K=1
1≤N≤1000
子任务 2 (14 分)
K=1
1≤N≤100000
子任务 3 (9 分)
K=2
1≤N≤100
子任务 4 (32 分)
K=2
1≤N≤1000
子任务 5 (37 分)
K=2
1≤N≤100000
题解:
http://www.cnblogs.com/xkui/p/4536421.html
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 typedef long long int64; 8 const int maxn=200005; 9 char c1[2],c2[2]; 10 int k,n,l,r,cnt,tot,a[maxn],b[maxn]; 11 int64 ans; 12 struct Data{ 13 int l,r,idl,idr,v; 14 }list[maxn]; 15 bool cmp(const Data &x,const Data &y){return x.v<y.v;} 16 struct seg{ 17 #define ls k<<1 18 #define rs (k<<1)+1 19 int cnt[maxn<<2]; 20 void modify(int k,int l,int r,int x,int v){ 21 cnt[k]+=v; 22 if (l==r) return; 23 int m=(l+r)>>1; 24 if (x<=m) modify(ls,l,m,x,v); else modify(rs,m+1,r,x,v); 25 } 26 void modify(int x,int v){modify(1,1,tot,x,v);} 27 int query(int rank){ 28 int k=1,l=1,r=tot,m; 29 while (l<r){ 30 m=(l+r)>>1; 31 if (rank<=cnt[ls]) r=m,k=ls; 32 else rank-=cnt[ls],l=m+1,k=rs; 33 } 34 return l; 35 } 36 }T[2]; 37 void prepare(){ 38 for (int i=1;i<=cnt;i++) b[++tot]=list[i].l,b[++tot]=list[i].r; 39 sort(b+1,b+tot+1); 40 for (int i=1;i<=cnt;i++){ 41 list[i].idl=lower_bound(b+1,b+tot+1,list[i].l)-b; 42 list[i].idr=lower_bound(b+1,b+tot+1,list[i].r)-b; 43 } 44 } 45 int64 solve(){ 46 int64 res=0,ans1=0,ans2=0,m1=0,m2=0; 47 prepare(); 48 for (int i=1;i<=cnt;i++) T[1].modify(list[i].idl,+1),T[1].modify(list[i].idr,+1); 49 for (int i=1;i<=cnt;i++) list[i].v=list[i].l+list[i].r; 50 sort(list+1,list+cnt+1,cmp),m2=b[cnt+1]; 51 for (int i=1;i<=cnt;i++) ans2+=abs(list[i].l-m2),ans2+=abs(list[i].r-m2); 52 res=ans2; 53 for (int i=1;i<=cnt;i++){ 54 ans2-=abs(list[i].l-m2)+abs(list[i].r-m2); 55 T[0].modify(list[i].idl,+1),T[0].modify(list[i].idr,+1),m1=b[T[0].query(i)]; 56 T[1].modify(list[i].idl,-1),T[1].modify(list[i].idr,-1),m2=b[T[1].query(cnt-i+1)]; 57 ans1+=abs(list[i].l-m1)+abs(list[i].r-m1); 58 res=min(res,ans1+ans2); 59 } 60 return res; 61 } 62 int main(){ 63 scanf("%d%d",&k,&n); 64 if (k==1){ 65 for (int i=1;i<=n;i++){ 66 scanf("%s%d%s%d",c1,&l,c2,&r); 67 if (l>r) swap(l,r); 68 if (c1[0]==c2[0]) ans+=r-l; 69 else a[++tot]=l,a[++tot]=r,ans++; 70 } 71 sort(a+1,a+tot+1); 72 int res=a[tot/2]; 73 for (int i=1;i<=tot;i++) ans+=abs(a[i]-res); 74 printf("%lld ",ans); 75 } 76 else{ 77 for (int i=1;i<=n;i++){ 78 scanf("%s%d%s%d",c1,&l,c2,&r); 79 if (l>r) swap(l,r); 80 if (c1[0]==c2[0]) ans+=r-l; 81 else ans++,list[++cnt]=(Data){l,r}; 82 } 83 printf("%lld ",ans+solve()); 84 } 85 return 0; 86 }