4071: [Apio2015]巴邻旁之桥

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

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\n",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\n",ans+solve());
84     }
85     return 0;
86 }

 

posted @ 2016-04-25 16:21  chenyushuo  阅读(281)  评论(0编辑  收藏  举报