zoukankan      html  css  js  c++  java
  • 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
    ",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 }
  • 相关阅读:
    [转]sql语句优化原则
    [Effective C++]构造/析构/赋值运算
    [Effective C++]定制new和delete
    [Effective C++]让自己习惯C++
    [C++ primer]联合:节省空间的类
    [C++ primer]类成员指针
    [C++ primer]运行时类型识别(RTTI)
    [APUE]fork后子进程的运行情况
    [C++ primer]优化内存分配
    [C++ primer]虚函数和纯虚函数
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5431373.html
Copyright © 2011-2022 走看看