【LOJ】#2888. 「APIO2015」巴邻旁之桥 Palembang Bridges

题解

发现我们选择一座桥会选择力\(\frac{s + t}{2}\)较近的一座桥

然后我们只需要按照\(s + t\)排序,然后枚举断点,左边取所有s和t的中位数,右边同理

动态求中位数用平衡树维护

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 100005
#define mp make_pair
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 + c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
struct Seg {
    int64 s,t,d;
    friend bool operator < (const Seg &a,const Seg &b) {
	return a.d < b.d;
    }
}seg[MAXN];
u32 Rand() {
    static u32 x = 1736382156;
    return x += x << 2 | 1;
}
struct Treap_node {
    Treap_node *lc,*rc;
    int64 sum,val;int siz;
    u32 pri;
    void update() {
	sum = val;siz = 1;
	if(lc) {sum += lc->sum;siz += lc->siz;}
	if(rc) {sum += rc->sum;siz += rc->siz;}
    }
}pool[MAXN * 4],*tail = pool,*rt;
Treap_node* Newnode(int64 v) {
    Treap_node *res = tail++;
    res->lc = res->rc = NULL;res->sum = res->val = v;
    res->siz = 1;res->pri = Rand();
    return res;
}
Treap_node* Merge(Treap_node *A,Treap_node *B) {
    if(!A) return B;
    if(!B) return A;
    if(A->pri < B->pri) {
	A->rc = Merge(A->rc,B);
	A->update();
	return A;
    }
    else {
	B->lc = Merge(A,B->lc);
	B->update();
	return B;
    }
}
void Split(Treap_node *u,Treap_node *&L,Treap_node *&R,int64 v,bool on) {
    if(!u) {L = R = NULL;return;}
    int t;
    if(!on) t = u->lc ? u->lc->siz + 1 : 1;
    else t = u->val;
    if(v >= t) {
	L = u;
	if(!on) v -= t;
	Split(u->rc,L->rc,R,v,on);
	L->update();
    }
    else {
	R = u;
	Split(u->lc,L,R->lc,v,on);
	R->update();
    }
}
void Insert(Treap_node *&rt,int64 v) {
    Treap_node *L,*R;
    Split(rt,L,R,v,1);
    rt = Merge(Merge(L,Newnode(v)),R);
}
int64 Calc(Treap_node *&rt) {
    int s = rt->siz / 2;
    Treap_node *L,*R,*p;
    Split(rt,L,R,s,0);
    int64 res = R->sum - L->sum;
    rt = Merge(L,R);
    return res;
}
int64 ans,f[MAXN],b[MAXN];
int K,N,tot;
void Solve() {
    read(K);read(N);
    char p[4],q[4];int64 s,t;
    for(int i = 1 ; i <= N ; ++i) {
	scanf("%s",p + 1);read(s);scanf("%s",q + 1);read(t);
	if(s > t) swap(s,t);
	if(p[1] == q[1]) ans += t - s;
	else {
	    ++ans;
	    seg[++tot] = (Seg){s,t,s + t}; 
	}
    }
    sort(seg + 1,seg + tot + 1);
    f[0] = 0;rt = NULL;
    for(int i = 1 ; i <= tot ; ++i) {
	Insert(rt,seg[i].s);Insert(rt,seg[i].t);
	f[i] = Calc(rt);
    }
    b[tot + 1] = 0;
    tail = pool;rt = NULL;
    for(int i = tot ; i >= 1 ; --i) {
	Insert(rt,seg[i].s);Insert(rt,seg[i].t);
	b[i] = Calc(rt);
    }
    if(K == 1) {out(f[tot] + ans);enter;}
    else {
	int64 tmp = f[tot];
	for(int i = 0 ; i <= tot ; ++i) tmp = min(tmp,f[i] + b[i + 1]);
	out(tmp + ans);enter;
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}
posted @ 2018-10-23 17:37  sigongzi  阅读(323)  评论(0编辑  收藏  举报