ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-06-26 23:44:21  阅读:224  来源: 互联网

标签:qr return 巴邻 int mid 八邻 query ql 旁之桥


题目描述:

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;
}
View Code

 

标签:qr,return,巴邻,int,mid,八邻,query,ql,旁之桥
来源: https://www.cnblogs.com/LiGuanlin1124/p/11094530.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有