• [APIO2015]八邻旁之桥


    题目描述

    一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 AA 和区域 BB 。

    每一块区域沿着河岸都建了恰好 10000000011000000001 栋的建筑,每条岸边的建筑都从 00 编号到 10000000001000000000 。相邻的每对建筑相隔 11 个单位距离,河的宽度也是 11 个单位长度。区域 AA 中的 ii 号建筑物恰好与区域 BB 中的 ii 号建筑物隔河相对。

    城市中有 NN 个居民。第 ii 个居民的房子在区域 P_iPi 的 S_iSi 号建筑上,同时他的办公室坐落在 Q_iQi 区域的 T_iTi 号建筑上。一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过 KK 座横跨河流的大桥。

    由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。

    当政府建造最多 KK 座桥之后,设 D_iDi 表示第 ii 个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得 D_1 + D_2 + cdots + D_ND1+D2++DN 最小。

    输入输出格式

    输入格式:

    输入的第一行包含两个正整数 KK 和 NN ,分别表示桥的上限数量和居民的数量。

    接下来 NN 行,每一行包含四个参数: P_i, S_i, Q_iPi,Si,Qi 和 T_iTi ,表示第 ii 个居民的房子在区域 P_iPi 的 S_iSi 号建筑上,且他的办公室位于 Q_iQi 区域的 T_iTi 号建筑上。

    输出格式:

    输出仅为一行,包含一个整数,表示 D_1 + D_2 + cdots + D_ND1+D2++DN 的最小值。

    输入输出样例

    输入样例#1: 复制
    1 5
    B 0 A 4
    B 1 B 3
    A 5 B 7
    B 2 A 6
    B 1 A 7
    输出样例#1: 复制
    24
    
    输入样例#2: 复制
    2 5
    B 0 A 4
    B 1 B 3
    A 5 B 7
    B 2 A 6
    B 1 A 7
    输出样例#2: 复制
    22

    说明

    【数据范围】

    所有数据都保证: P_iPi 和 Q_iQi 为字符 “A” 和 “B” 中的一个, 0 leq S_i, T_i leq 10000000000Si,Ti1000000000 ,同一栋建筑内可能有超过 11 间房子或办公室(或二者的组合,即房子或办公室的数量同时大于等于 11 )。

    子任务 1 (8 分) K = 1K=1

    1 leq N leq 10001N1000

    子任务 2 (14 分) K = 1K=1

    1 leq N leq 1000001N100000

    子任务 3 (9 分) K = 2K=2

    1 leq N leq 1001N100

    子任务 4 (32 分) K = 2K=2

    1 leq N leq 10001N1000

    子任务 5 (37 分) K = 2K=2

    1 leq N leq 1000001N100000

    在同一边的可以直接无视

    k=1时

    取所有的居民的(家坐标+公司坐标)/2的所有坐标的正中间建一座桥,使所有居民到的距离最小。

    k=2时

    取每个线段的中点,如果靠近左边的桥,就往左边过桥,否则往右边过桥。

    这样的话,先把线段按l+r排序,如果枚举一个分割线,左右两边分别转换成为K=1的情况了

    用离散+线段树查找中位数

    f[i]表示1~i中的居民走一座桥

    然后从后往前再算一次,答案是min(f[i]+ans(i+1~n))

    如果是k=1直接输出f[n]

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 typedef long long lol;
      8 struct ZYYS
      9 {
     10   int l,r;
     11 }d[200001];
     12 lol p[400001];
     13 int cnt,tot,n,k;
     14 lol s[1600001],c[1600001],flag,delta,f[200001],ans;
     15 char s1[6],s2[6];
     16 bool cmp(ZYYS a,ZYYS b)
     17 {
     18   return a.l+a.r<b.l+b.r;
     19 }
     20 void pushup(int rt)
     21 {
     22   s[rt]=(s[rt*2]+s[rt*2+1]);
     23   c[rt]=(c[rt*2]+c[rt*2+1]);
     24 }
     25 void update(int rt,int l,int r,int x,lol d)
     26 {
     27   if (l==r)
     28     {
     29       c[rt]++;
     30       s[rt]+=d;
     31       return;
     32     }
     33   int mid=(l+r)/2;
     34   if (x<=mid) update(rt<<1,l,mid,x,d);
     35   else update(rt<<1|1,mid+1,r,x,d);
     36   pushup(rt);
     37 }
     38 lol query(int rt,int l,int r,int x)
     39 {
     40   if (l==r)
     41     {
     42       return p[l]*x;
     43     }
     44   int mid=(l+r)/2;
     45   if (c[rt*2]<x) return s[rt*2]+query(rt*2+1,mid+1,r,x-c[rt*2]);
     46   else return query(rt*2,l,mid,x);
     47 }
     48 lol cal(int x)
     49 {
     50   lol tmp=query(1,1,tot,x);
     51   return s[1]-2*tmp;
     52 }
     53 int main()
     54 {int x,y,i;
     55   cin>>k>>n;
     56   for (i=1;i<=n;i++)
     57     {
     58       scanf("%s%d%s%d",s1,&x,s2,&y);
     59       if (x>y) swap(x,y);
     60       if (s1[0]==s2[0])
     61     delta+=y-x;
     62       else
     63     {
     64       delta++;
     65       d[++cnt]=(ZYYS){x,y};
     66       p[++tot]=x;p[++tot]=y;
     67     }
     68     }
     69   n=cnt;
     70   sort(p+1,p+tot+1);
     71   cnt=unique(p+1,p+tot+1)-p-1;
     72   tot=cnt;
     73   sort(d+1,d+n+1,cmp);
     74   for (i=1;i<=n;i++)
     75     {
     76       d[i].l=lower_bound(p+1,p+tot+1,d[i].l)-p;
     77       d[i].r=lower_bound(p+1,p+tot+1,d[i].r)-p;
     78     }
     79   for (i=1;i<=n;i++)
     80     {
     81       update(1,1,tot,d[i].l,p[d[i].l]);
     82       update(1,1,tot,d[i].r,p[d[i].r]);
     83       f[i]=cal(i);
     84     }
     85   if (k==1)
     86     {
     87       cout<<f[n]+delta;
     88       return 0;
     89     }
     90   memset(s,0,sizeof(s));
     91   memset(c,0,sizeof(c));
     92   ans=f[n];
     93   for (i=n;i>=1;i--)
     94     {
     95       update(1,1,tot,d[i].l,p[d[i].l]);
     96       update(1,1,tot,d[i].r,p[d[i].r]);
     97       ans=min(ans,f[i-1]+cal(n-i+1));
     98     }
     99   cout<<ans+delta;
    100 }
  • 相关阅读:
    《算法导论》读书笔记--第三章函数的增长 课后题
    《利用python进行数据分析》读书笔记--第五章 pandas入门
    《利用python进行数据分析》读书笔记--第四章 numpy基础:数组和矢量计算
    《利用python进行数据分析》读书笔记--第三章 ipython使用
    《算法导论》读书笔记--第三章 函数的增长
    《利用python进行数据分析》读书笔记 --第一、二章 准备与例子
    《R语言实战》读书笔记--学习张丹日志
    《R语言实战》读书笔记 第七章--基本统计分析
    解决Mybatis-plus高版本不向后兼容的问题
    【Javascript】: for循环中定义的变量在for循环体外也有效
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8908870.html
Copyright © 2020-2023  润新知