【BZOJ 4071】 [Apio2015]巴鄰旁之橋,bzojapio2015

來源:互聯網
上載者:User

【BZOJ 4071】 [Apio2015]巴鄰旁之橋,bzojapio2015

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 respective side of the river, conveniently numbered 0 through 1,000,000,000. The distance between every pair of adjacent buildings is 1 unit of distance. The width of the river is 1 unit of distance as well. Building i in zone A is located on exactly the opposite side of building i in zone B.

N citizens live and work in the city. Citizen i’s house is in zone Pi, building Si, while his office is in zone Qi, building Ti. If a citizen must cross the river to go from his house to his office, he must take a boat. This has been uncomfortable, so the government has decided to build at most K bridges over the river, so that the citizens can go to work by driving. Each bridge must be built exactly between two opposite buildings in the two zones. The bridges must be strictly perpendicular to the river. The bridges must not overlap each other.

Let Di be the minimum distance citizen i has to drive to go from his house to his office, after the government has built at most K bridges. Help the government build the bridges in such a way that the sum D1 + D2 + … + DN is minimized.

Input Format

The first line contains two integers K and N. Each of the next N lines contains four tokens Pi, Si, Qi, and Ti.

Output Format

A single line containing the minimum sum of the distances.

Sample Input 1

1 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7
Sample Output 1

24
Sample Input 2

2 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7
Sample Output 2

22
Explanation

This is the illustration for both sample inputs.

Here is one possible solution for sample input 1. The pink stripe segment denotes a bridge.

And this is a possible solution for sample input 2:

Subtasks

For each subtask,

Pi and Qi will be either a character ‘A’ or a character ‘B’.
0 ≤ Si, Ti ≤ 1,000,000,000
More than one house or office (or combination of both) can be located in the same building.
Subtask 1 (8 points)

K = 1
1 ≤ N ≤ 1,000
Subtask 2 (14 points)

K = 1
1 ≤ N ≤ 100,000
Subtask 3 (9 points)

K = 2
1 ≤ N ≤ 100
Subtask 4 (32 points)

K = 2
1 ≤ N ≤ 1,000
Subtask 5 (37 points)

K = 2
1 ≤ N ≤ 100,000

權值線段樹動態維護中位元。

(家和單位在同一側的提前算好)
當把所求的計算式列出之後,可以發現最優解是所有辦公室和家的位置的中位元。

對於k=1的,中位元可以直接求出。

對於k=2的,可以發現:按照每個人的家和辦公室的中點排序後,一定存在一個分割點使得首碼都走左邊的橋,尾碼都走右邊的橋(因為走靠近中點的橋不會更差)。

於是我們枚舉分割點,離散化後用權值線段樹動態維護兩個區間的中位元求解即可。

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <map>#include <vector>#define pb push_back#define M 300005#define LL long longusing namespace std;LL ans[M];int size,n,k,cnt;int ls[M],d[M];char s1[10],s2[10];struct data{    int x[3];}a[M];struct Segtree{    int size;    LL sum;}t[M<<2];int z[10];void lisan(){    sort(ls+1,ls+1+cnt);    size=unique(ls+1,ls+1+cnt)-ls-1;}int Hash(int x){    return lower_bound(ls+1,ls+1+size,x)-ls;}bool cmp(data a,data b){    return a.x[1]+a.x[2]<b.x[1]+b.x[2];}void Update(int x){    t[x].sum=t[x<<1].sum+t[x<<1|1].sum;    t[x].size=t[x<<1].size+t[x<<1|1].size;}void Build(int x,int l,int r){    if (l==r)    {        t[x].sum=t[x].size=0;        return;    }    int m=(l+r)>>1;    Build(x<<1,l,m);    Build(x<<1|1,m+1,r);    Update(x);}void Insert(int x,int l,int r,int k){    if (l==r)    {        t[x].sum+=d[l];        t[x].size++;        return;    }    int m=(l+r)>>1;    if (k<=m) Insert(x<<1,l,m,k);    else Insert(x<<1|1,m+1,r,k);    Update(x);}LL Getsum(int x,int l,int r,int cnt){    if (t[x].size<=cnt)        return t[x].sum;    if (l==r)        return 1LL*cnt*d[l];    int m=(l+r)>>1;    if (t[x<<1].size>=cnt) return Getsum(x<<1,l,m,cnt);    else return t[x<<1].sum+Getsum(x<<1|1,m+1,r,cnt-t[x<<1].size);}LL Query(LL k){    LL s=Getsum(1,1,size,k);    return t[1].sum-2LL*s;}int main(){    scanf("%d%d",&k,&n);    LL pre=0;    int tot=0;    cnt=0;    for (int i=1;i<=n;i++)    {        int x1,x2;        scanf("%s%d%s%d",s1,&x1,s2,&x2);        if (s1[0]==s2[0])        {            pre+=abs(x1-x2);            continue;        }        pre++;        a[++tot].x[1]=x1,a[tot].x[2]=x2;        ls[++cnt]=x1,ls[++cnt]=x2;    }    if (cnt)    {        lisan();        n=tot;        for (int i=1;i<=n;i++)            d[Hash(a[i].x[1])]=a[i].x[1],d[Hash(a[i].x[2])]=a[i].x[2];        Build(1,1,size);        sort(a+1,a+1+n,cmp);        for (int i=1;i<=n;i++)        {            Insert(1,1,size,Hash(a[i].x[1]));            Insert(1,1,size,Hash(a[i].x[2]));            ans[i]=Query(i);        }    }    if (k==1)        cout<<ans[n]+pre<<endl;    else    {        LL Ans=ans[n];        if (size)        {            Build(1,1,size);            for (int i=n;i>1;i--)            {                Insert(1,1,size,Hash(a[i].x[1]));                Insert(1,1,size,Hash(a[i].x[2]));                Ans=min(Ans,ans[i-1]+Query(n-i+1));            }        }        cout<<Ans+pre<<endl;    }    return 0;}

這道題的關鍵在於發現要求的是中位元,以及按照中點排序後的性質。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.