APIO2015 八邻旁之桥/巴邻旁之桥

题目描述:

bz

luogu

题解:

贪心+权值线段树。

$K=1$的时候,答案为$\sum |x-l| + |x-r|$,所以所有端点排序后取中位数即可。

$K=2$的时候,一定是左边的一些走左边的桥,右边的一些走右边的桥。

问题是按什么顺序排序。

答案是按线段中点排序。

原因是,对于河两岸的一对点和两座桥,选择的一定是离线段中点近的那个。

考虑如何快速计算答案,我们可以用权值线段树维护区间和与中位数。(当然也可以用平衡树)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100050;
const int M = 100*N;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){c=c*10+ch-‘0‘;ch=getchar();}
    x = f*c;
}
int K,n;
ll ans;
char op1[2],op2[2];
struct Point
{
    int l,r;
    Point(){}
    Point(int l,int r):l(l),r(r){}
    bool operator < (const Point&a)const{return l+r<a.l+a.r;}
}p[N];
int s[N<<1],tl;
const int inf = 2000000001;
struct segtree
{
    int rt,tot,ls[M],rs[M],siz[M];
    ll sum[M];
    void insert(int l,int r,int&u,int qx)
    {
        if(!u)u=++tot;siz[u]++,sum[u]+=qx;
        if(l==r)return ;
        int mid = (l+r)>>1;
        if(qx<=mid)insert(l,mid,ls[u],qx);
        else insert(mid+1,r,rs[u],qx);
    }
    void erase(int l,int r,int u,int qx)
    {
        siz[u]--,sum[u]-=qx;if(l==r)return ;
        int mid = (l+r)>>1;
        if(qx<=mid)erase(l,mid,ls[u],qx);
        else erase(mid+1,r,rs[u],qx);
    }
    int query(int l,int r,int u,int rk)
    {
        if(!u)return -1;
        if(l==r)return l;
        int mid = (l+r)>>1;
        if(rk<=siz[ls[u]])return query(l,mid,ls[u],rk);
        else return query(mid+1,r,rs[u],rk-siz[ls[u]]);
    }
    ll query(int l,int r,int u,int ql,int qr)
    {
        if(!u||ql>qr)return 0;
        if(l==ql&&r==qr)return sum[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,ls[u],ql,qr);
        else if(ql>mid)return query(mid+1,r,rs[u],ql,qr);
        else return query(l,mid,ls[u],ql,mid)+query(mid+1,r,rs[u],mid+1,qr);
    }
    ll Query(int l,int r,int u,int ql,int qr)
    {
        if(!u||ql>qr)return 0;
        if(l==ql&&r==qr)return siz[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return Query(l,mid,ls[u],ql,qr);
        else if(ql>mid)return Query(mid+1,r,rs[u],ql,qr);
        else return Query(l,mid,ls[u],ql,mid)+Query(mid+1,r,rs[u],mid+1,qr);
    }
    ll query(int siz)
    {
        int mid = query(0,inf,rt,siz);
        ll ql = query(0,inf,rt,0,mid-1),qr = query(0,inf,rt,mid+1,inf),tmp = (Query(0,inf,rt,mid+1,inf)-Query(0,inf,rt,0,mid-1));
        return qr-ql-tmp*mid;
    }
}tr[2];
int main()
{
//    freopen("tt.in","r",stdin);
    read(K),read(n);
    for(int x,y,i=1;i<=n;i++)
    {
        scanf("%s",op1),read(x),scanf("%s",op2),read(y);
        if(x>y)swap(x,y);
        if(op1[0]==op2[0])
        {
            ans+=y-x;
            i--,n--;
        }else p[i]=Point(x,y);
    }
    ans+=n;
    if(!n)
    {
        printf("%lld\n",ans);
        return 0;
    }
    if(K==1)
    {
        for(int i=1;i<=n;i++)
            s[++tl]=p[i].l,s[++tl]=p[i].r;
        sort(s+1,s+tl+1);
        int mid = (s[tl/2]+s[tl/2+1])/2;
        int i;
        for(i=1;s[i]<=mid;i++)ans+=mid-s[i];
        for(;i<=tl;i++)ans+=s[i]-mid;
        printf("%lld\n",ans);
        return 0;
    }
    sort(p+1,p+1+n);
    for(int i=1;i<=n;i++)
        tr[1].insert(0,inf,tr[1].rt,p[i].l),tr[1].insert(0,inf,tr[1].rt,p[i].r);
    ll mx = 0x3f3f3f3f3f3f3f3fll;
    for(int i=1;i<=n;i++)
    {
        tr[0].insert(0,inf,tr[0].rt,p[i].l),tr[0].insert(0,inf,tr[0].rt,p[i].r);
        tr[1].erase (0,inf,tr[1].rt,p[i].l),tr[1].erase (0,inf,tr[1].rt,p[i].r);
        mx=min(mx,tr[0].query(i)+tr[1].query(n-i));
    }
    printf("%lld\n",ans+mx);
    return 0;
}

原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11094530.html

时间: 2024-10-10 16:43:31

APIO2015 八邻旁之桥/巴邻旁之桥的相关文章

【BZOJ 4071】[apio2015]巴邻旁之桥

4071:[apio2015]巴邻旁之桥 Time limit: 2000 ms Memory limit: 262144 KB Description The city of Palembang is separated by Musi River into two zones. Let's call them zone A and zone B. Each zone consists of exactly 1,000,000,001 buildings along the respectiv

【bzoj4071】[Apio2015]巴邻旁之桥 Treap

题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000.相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度.区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对. 城市中有 N 个居民.第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上.一个居民的房子和办公室可能分布在河

4071: [Apio2015]巴邻旁之桥

Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000.相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度.区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对. 城市中有 N 个居民.第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上.一个居民的房子和办公

BZOJ4071 &amp; 洛谷3644:[APIO2015]巴邻旁之桥——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=4071 https://www.luogu.org/problemnew/show/P3644 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000.相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度.区域 A 中的 i 号建筑物恰好与区域 B 中的

[APIO2015]八邻旁之桥

题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 AA 和区域 BB . 每一块区域沿着河岸都建了恰好 10000000011000000001 栋的建筑,每条岸边的建筑都从 00 编号到 10000000001000000000 .相邻的每对建筑相隔 11 个单位距离,河的宽度也是 11 个单位长度.区域 AA 中的 ii 号建筑物恰好与区域 BB 中的 ii 号建筑物隔河相对. 城市中有 NN 个居民.第 ii 个居民的房子在区域 P_iPi? 的 S_iSi? 号建筑上,同时

机器学习算法一:K-近邻算法

最近在<机器学习实战>里学习了一些基本的算法,对于一个纯新手我也在网上找了写资料,下面就我在书上所看的加上在其他博客上的内容做一个总结,博客请参照http://www.cnblogs.com/BaiYiShaoNian/p/4567446.html K-近邻算法 K-近邻算法就是采用测量不同特征值之间的距离方法来进行分类. 优点:精度高,对异常值不敏感,无数据输入假定. 缺点:计算复杂度高,空间复杂度高. 适用范围:数值型和标称型. 工作原理: 存在一个样本数据集合,也称作训练样本集,并且样本

机器学习实战之第二章 k-近邻算法

第2章 k-近邻算法 KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片:亲吻次数更多 基于电影中的亲吻.打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型. 现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影. 假定 k=3,则三个最靠近的电影依次是, He's Not

技术邻学院 直播预告|【进阶】simufact软件焊接仿真工艺培训

技术邻学院 直播预告 [进阶]simufact软件焊接仿真工艺培训 (6月10日) 直播信息 日期: 2017年6月10日(星期六)20:00--21:30 直播地址: 熊猫直播http://panda.tv/1028790   房间ID:1028790 主讲人: 卢鸣飞  高级工程师 毕业于复旦大学力学系.后就职于德国SIMUFACT软件的中国总代理处,做技术支持工程师,为中车.商飞.一汽.上海电气集团以及南航.哈工大和清华大学等近百家单位提供技术支持. 技术邻ID:卢鸣飞  熟悉simufa

【IPv6】邻节点不可到达检测学习(NUD)

邻节点不可到达检测 邻节点不可到达检测方法有2种: 1. 通过发送单播邻节点请求报文和接收响应请求的邻节点公告报文来完成. 2. 借助上层协议确定可达性.(TCP) 通过NS/NA报文进行NUD检测 响应请求的邻节点公告报文仅用于响应邻节点请求报文,响应请求的邻节点公告报文会将其报文中的请求标志置为1.(响应时,NA报文中请求标志位设为1). 自发的邻节点公告报文或路由器公告报文并不能用于验证可达性. 邻节点请求报文和邻节点公告报文的交互仅能确认从发送邻节点请求报文的节点A到发送邻节点公告报文的