bzoj4071 [Apio2015]Bridge line segment tree next to Ba Lin

Description


An east-west direction of the Musi River divides the city of Palingbang into two parts, area A and area B.

Exactly 1000000001 buildings are built along the banks of each area, and the buildings along each bank are numbered from 0 to 1000000000. Each adjacent pair of buildings is 1 unit distance apart, and the width of the river is also 1 unit length. Building i in area A is just across the river from building i in area B.
There are N residents in the city. The i-th resident's house is on building Si in area Pi, while his office is located on building Ti in Qi area. A resident's house and office may be on both sides of the river, so he has to take a boat to get from his home to his office, a situation that many people find inconvenient. To allow residents to drive to work, the government decided to build no more than K bridges across the river.
For technical reasons, each bridge must connect just two sides of the river, the bridges must be strictly perpendicular to the river, and the bridges must not intersect. After the government has built at most K bridges, let Di denote the shortest distance that the ith resident drives from his home to his office at this time. Please help the government to build bridges so that D1+D2+⋯+DN is the smallest.

1<=K<=2
1≤N≤100000

Solution


At the beginning, I felt it at random and found that when k=1, it is a concave function, when k=2, it can be divided into three points, and one wave of belief is T. But three points have 65pts wow

Positive solution: When k=1, the answer is the median. When k=2, the dividing line is enumerated. The median of the left half and the median of the right half are the answer. Two weight line segment trees are used to support insertion, delete, find the median

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define fi first
#define se second

typedef std:: pair <double,int> pair;
typedef long long LL;
const int N=200005;

struct segTree {
    int size[N*30],l[N*30],r[N*30],root,tot;
    LL sum[N*30];

    void modify(int &now,int tl,int tr,int x,int v) {
        if (!now) now=++tot;
        sum[now]+=x*v; size[now]+=v;
        if (tl==tr) return ;
        int mid=(tl+tr)>>1;
        if (x<=mid) modify(l[now],tl,mid,x,v);
        else modify(r[now],mid+1,tr,x,v);
    }

    LL query(int now,int tl,int tr,int x) {
        if (tr<=x) return (LL)x*size[now]-sum[now];
        if (x<=tl) return sum[now]-(LL)x*size[now];
        int mid=(tl+tr)>>1;
        return query(l[now],tl,mid,x)+query(r[now],mid+1,tr,x);
    }

    int kth(int now,int tl,int tr,int k) {
        if (tl==tr) return tl;
        int mid=(tl+tr)>>1;
        if (k<=size[l[now]]) return kth(l[now],tl,mid,k);
        else return kth(r[now],mid+1,tr,k-size[l[now]]);
    }
} t1,t2;

struct Q {int x,y;} q[N];

pair vec2[N];

LL vec1[N];
LL L[N],R[N];

LL myabs(LL x) {
    return (x<0)?(-x):(x);
}

void solve1(int n) {
    LL ans=0; int tot=0;
    rep(i,1,n) {
        char opt1[2],opt2[2];
        LL x1,x2; scanf("%s%lld%s%lld",&opt1,&x1,&opt2,&x2);
        if (opt1[0]==opt2[0]) ans+=myabs(x1-x2);
        else vec1[++tot]=x1,vec1[++tot]=x2,ans++;
    }
    std:: sort(vec1+1,vec1+tot+1);
    LL pos=vec1[(tot+1)/2];
    rep(i,1,tot) ans+=myabs(pos-vec1[i]);
    printf("%lld\n", ans);
}

LL calc() {
    int p1=t1.kth(t1.root,0,1000000000,(1+t1.size[t1.root])/2);
    int p2=t2.kth(t2.root,0,1000000000,(1+t2.size[t2.root])/2);
    return t1.query(t1.root,0,1000000000,p1)+t2.query(t2.root,0,1000000000,p2);
}

void solve2(int n) {
    LL pre=0; int tot=0;
    rep(i,1,n) {
        char opt1[2],opt2[2];
        scanf("%s%d%s%d",&opt1,&L[i],&opt2,&R[i]);
        if (L[i]>R[i]) std:: swap(L[i],R[i]);
        if (opt1[0]==opt2[0]) {
            pre+=myabs(L[i]-R[i]);
            i--,n--;
        } else {
            vec2[++tot]=pair(0.5*(L[i]+R[i]),i);
            pre++;
        }
    }
    std:: sort(vec2+1,vec2+tot+1);
    rep(i,1,tot) {
        t2.modify(t2.root,0,1000000000,L[vec2[i].se],1);
        t2.modify(t2.root,0,1000000000,R[vec2[i].se],1);
    }
    LL ans=calc()+pre;
    rep(i,1,tot-1) {
        t2.modify(t2.root,0,1000000000,L[vec2[i].se],-1);
        t2.modify(t2.root,0,1000000000,R[vec2[i].se],-1);
        t1.modify(t1.root,0,1000000000,L[vec2[i].se],1);
        t1.modify(t1.root,0,1000000000,R[vec2[i].se],1);
        ans=std:: min(ans,pre+calc());
    }
    printf("%lld\n", ans);
}

int main(void) {
    t1.root=t1.tot=t2.root=t2.tot=0;
    int k,n; scanf("%d%d",&k,&n);
    if (k==1) solve1(n);
    else solve2(n);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324839592&siteId=291194637