zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",ans+mx);
        return 0;
    }
    View Code
  • 相关阅读:
    输出python的help结果到文件中
    webdriver 的三种等待方式
    Loadrunner 怎么将response的数据下载下来
    Loadrunner web_reg_find 和web_reg_save_param 比较
    LR的响应时间与使用IE所感受时间不一致的讨论
    Loadrunner错误-26601、-27492、-27727处理方法
    loadrunner运行乱码解决方法
    OpenGL ES: (1) OpenGL ES的由来 (转)
    JPG:文件格式系列科普之.JPEG/.JPG(转)
    单色位图、16色位图、256色位图的含义
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11094530.html
Copyright © 2011-2022 走看看