4071:[APIO2015] Palembang next to the bridge

Time limit:2000 ms

Memory limit:262144 KB

Description

The city of Palembang are separated by Musi and into the other 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 thro Ugh 1,000,000,000. The distance between every pair of adjacent buildings is 1 unit of distance. The width of the river was 1 unit of distance as well. Building I in zone A are located on exactly the opposite side of Building I in zone B.

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

Let Di is the minimum distance citizen I have to drive to go from he house to he office, after the government have built a T most K bridges. Help the Government build, the bridges in such a, the sum D1 + D2 + ... + DN is minimized.

Input Format

The first line contains the 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 was the illustration for both sample inputs.

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

And this was a possible solution for sample input 2:

Subtasks

For each subtask,

Pi and Qi would 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 is located in the same building.

Subtask 1 (8 points)

K = 1

1≤n≤1,000

Subtask 2 (points)

K = 1

1≤n≤100,000

Subtask 3 (9 points)

K = 2

1≤n≤100

Subtask 4 (points)

K = 2

1≤n≤1,000

Subtask 5 (PNS points)

K = 2

1≤n≤100,000

The weight segment tree dynamically maintains the median.

(Home and flat on the same side of the advance calculation)

When you list the calculated formula, you can find that the optimal solution is the median of all office and home locations.

For k=1 , the median can be calculated directly.

For k=2 , can be found: according to everyone's home and office*Midpoint*After sorting, there must be a split point so that the prefixes go to the left of the bridge, and the suffix goes to the right side of the bridge (because the bridge near the midpoint will not be worse).

Then we enumerate the dividing points, and then we can solve the two intervals of the dynamic maintenance of the weight segment tree.

`#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include < cstdlib> #include <cmath> #include <map> #include <Vector> #define PB push_back#define M300005#define LL Long LongusingnamespaceStd LL Ans[m];int size, n,k,cnt;int ls[M],d[m];char s1[Ten],s2[Ten];struct data{intx[3];} A[m];struct segtree{int size; LL sum;} t[m<<2];intz[Ten];void Lisan () {Sort(ls+1,ls+1+CNT);size=unique (ls+1,ls+1+CNT)-ls-1;}intHash (intx) {returnLower_bound (ls+1,ls+1+size, X)-ls;} BOOL CMP (data A,data b) {returna.x[1]+a.x[2]<b.x[1]+b.x[2];} void Update (intx) {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 (intXintLintR) {if(L==R) {t[x].sum=t[x].size=0;return; }intM= (l+r) >>1; Build (x<<1, l,m); Build (x<<1|1, m+1, R); Update (x);} void Insert (intXintLintRintK) {if(L==R) {T[x].sum+=d[l]; T[X].size++;return; }intM= (l+r) >>1;if(k<=m) Insert (x<<1, l,m,k);ElseInsert (x<<1|1, m+1, r,k); Update (x);} LL Getsum (intXintLintRintCNT) {if(T[x].size<=CNT)returnT[x].sum;if(L==R)return 1LL*cnt*d[L];intM= (l+r) >>1;if(t[x<<1].size>=CNT)returnGetsum (x<<1, l,m,cnt);Else returnt[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);returnt[1].sum-2LL*s;}intMain () {scanf ("%d%d", &k,&n); LL pre=0;inttot=0; Cnt=0; for(intI=1; i<=n;i++) {intx1,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(intI=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(intI=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(intI=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;}`

The key to this problem is to find the median, and the nature of sorting by the midpoint.

"Bzoj 4071" [apio2015] Palembang side Bridge