传送门

首先如果起点终点都在同一侧可以直接处理,如果需要过桥答案再加1

对于k等于1的情况

桥的坐标为x的话,a和b为起点和终点坐标

$ans=\sum_{1}^{n} abs(a_{i}-x)+abs(b_{i}-x)$

起点和终点显然可以合并

那么 $ans=\sum_{1}^{n} abs(a_{i}-x)$

x为中位数就是最优解

对于k等于2的情况

首先有个结论:$(a_{i}+b_{i})/2$ 离哪座桥近,就选择哪座桥

可以把坐标按照上面的公式排序,然后枚举中间点,分成左右两部分

每一部分都有一座桥,那么就需要一个可以维护中位数,求和,删除/增加一个数的数据结构

平衡树或者线段树都可以

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 200100
#define LL long long
#define root 1, 1, cnt
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r using namespace std; int k, n, m, cnt;
LL ans, tmp, tot, L[2], R[2];
int a[N];
char s[2]; struct node
{
int x, y;
}p[N]; struct tree
{
LL sum[N << 2], num[N << 2];
inline void update(int now, int l, int r, int x, int d)
{
num[now] += d, sum[now] += d * a[x];
if(l == r) return;
int mid = (l + r) >> 1;
if(x <= mid) update(ls, x, d);
else update(rs, x, d);
}
inline int find(int now, int l, int r, int x)
{
if(l == r)
{
L[0] += sum[now], L[1] += num[now];
return a[l];
}
int mid = (l + r) >> 1;
if(num[now << 1] >= x)
{
R[0] += sum[now << 1 | 1], R[1] += num[now << 1 | 1];
return find(ls, x);
}
else
{
L[0] += sum[now << 1], L[1] += num[now << 1];
return find(rs, x - num[now << 1]);
}
}
}t[2]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline void solve1()
{
int i, x;
for(i = 1; i <= n; i++)
{
scanf("%s", s), a[++m] = read();
scanf("%s", s + 1), a[++m] = read();
if(s[0] == s[1]) ans += abs(a[m] - a[m - 1]), m -= 2;
else ans++;
}
sort(a + 1, a + m + 1);
x = a[m >> 1];
for(i = 1; i <= m; i++) ans += abs(a[i] - x);
} inline bool cmp(node x, node y)
{
return x.x + x.y < y.x + y.y;
} inline void solve2()
{
int i, x;
for(i = 1; i <= n; i++)
{
m++;
scanf("%s", s), p[m].x = read();
scanf("%s", s + 1), p[m].y = read();
if(s[0] == s[1]) tot += abs(p[m].x - p[m].y), m--;
else tot++;
}
if(!m)
{
ans = tot; return;
}
sort(p + 1, p + m + 1, cmp);
for(i = 1; i <= m; i++) a[++cnt] = p[i].x, a[++cnt] = p[i].y;
sort(a + 1, a + cnt + 1);
cnt = unique(a + 1, a + cnt + 1) - a - 1;
for(i = 1; i <= m; i++)
p[i].x = lower_bound(a + 1, a + cnt + 1, p[i].x) - a,
p[i].y = lower_bound(a + 1, a + cnt + 1, p[i].y) - a;
for(i = 1; i <= m; i++)
t[1].update(root, p[i].x, 1), t[1].update(root, p[i].y, 1);
x = t[1].find(root, m);
ans = x * L[1] - L[0] + R[0] - x * R[1] + tot;
for(i = 1; i <= m; i++)
{
t[0].update(root, p[i].x, 1), t[0].update(root, p[i].y, 1);
t[1].update(root, p[i].x, -1), t[1].update(root, p[i].y, -1);
tmp = L[0] = L[1] = R[0] = R[1] = 0;
x = t[0].find(root, i);
tmp += x * L[1] - L[0] + R[0] - x * R[1];
L[0] = L[1] = R[0] = R[1] = 0;
x = t[1].find(root, m - i);
tmp += x * L[1] - L[0] + R[0] - x * R[1];
ans = min(ans, tmp + tot);
}
} int main()
{
k = read();
n = read();
if(k == 1) solve1();
if(k == 2) solve2();
printf("%lld\n", ans);
return 0;
}

  

[luoguP3644] [APIO2015]八邻旁之桥(权值线段树)的更多相关文章

  1. 题解【luoguP3644 [APIO2015]八邻旁之桥】

    题目链接 题解 家和公司在同侧 简单,直接预处理掉 若 \(k=1\) 取所有的居民的\(\frac{家坐标+公司坐标}{2}\)的所有坐标的正中间建一座桥,使所有居民到的距离最小. 实现方法:线段树 ...

  2. 洛谷 P3644 [APIO2015]八邻旁之桥 解题报告

    P3644 [APIO2015]八邻旁之桥 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好\(1000000001\)栋的建筑 ...

  3. [APIO2015]八邻旁之桥——非旋转treap

    题目链接: [APIO2015]八邻旁之桥 对于$k=1$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...

  4. [BZOJ4071][APIO2015]八邻旁之桥

    BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...

  5. APIO2015 八邻旁之桥/巴邻旁之桥

    题目描述: bz luogu 题解: 贪心+权值线段树. $K=1$的时候,答案为$\sum |x-l| + |x-r|$,所以所有端点排序后取中位数即可. $K=2$的时候,一定是左边的一些走左边的 ...

  6. [APIO2015]八邻旁之桥

    题面在这里 sol 这是一个\(Splay\)的题解 首先,如果一个人的家和办公室在同一侧,我们可以直接预处理; 如果不在同一侧,也可以加上1(当然要过桥啦) 当k==1时 我们设桥的位置为\(pos ...

  7. 洛谷 P3644 [APIO2015]八邻旁之桥(对顶堆维护中位数)

    题面传送门 题意: 一条河将大地分为 \(A,B\) 两个部分.两部分均可视为一根数轴. 有 \(n\) 名工人,第 \(i\) 名的家在 \(x_i\) 区域的 \(a_i\) 位置,公司在 \(y ...

  8. 【BZOJ4071】八邻旁之桥(线段树)

    [BZOJ4071]八邻旁之桥(线段树) 题面 BZOJ权限题,洛谷链接 题解 既然\(k<=2\) 那么,突破口就在这里 分类讨论 ①\(k=1\) 这...不就是中位数吗.... 直接把所有 ...

  9. 【BZOJ4071】[Apio2015]巴邻旁之桥 Treap

    [BZOJ4071][Apio2015]巴邻旁之桥 Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 ...

随机推荐

  1. 关于api接口

    前阵子一直疯狂的找关于php的api接口方面的资料来学习,总结了一下,无非就是请求数据,然后返回数据,当然也要设置相关安全措施,比如认证口令 等.返回数据格式是json 还是xml 看自己需求咯

  2. Phpstrom开发工具

    下载地址 https://www.jetbrains.com/zh/phpstorm/specials/phpstorm/phpstorm.html?utm_source=baidu&utm_ ...

  3. BZOJ2693: jzptab(莫比乌斯反演)

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2068  Solved: 834[Submit][Status][Discuss] Descripti ...

  4. VGA 时序标准

    VGA 显示器扫描方式从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT 对电子束进行消隐,每行结束时,用行同步信号进行同步:当扫描完所有的行 ...

  5. oracle杀死锁表的进程(转发+合并+自己实践)

    之一: Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作 (1)锁表查询的代码有以下的形式:select count(*) from v$locked_object;sel ...

  6. LeetCode:22. Generate Parentheses(Medium)

    1. 原题链接 https://leetcode.com/problems/generate-parentheses/description/ 2. 题目要求 给出一个正整数n,请求出由n对合法的圆括 ...

  7. LeetCode:18. 4Sum(Medium)

    1. 原题链接 https://leetcode.com/problems/4sum/description/ 2. 题目要求 给出整数数组S[n],在数组S中是否存在a,b,c,d四个整数,使得四个 ...

  8. Cyclone IV器件的逻辑单元和逻辑阵列快

    1. 逻辑单元 (LE) 在 Cyclone IV 器件结构中是最小的逻辑单位.LE 紧密且有效的提供了高级功能的逻辑使用.每个 LE 有以下特性:一个四口输入的查找表 (LUT),以实现四种变量的任 ...

  9. 「暑期训练」「Brute Force」 Bitonix' Patrol (CFR134D1D)

    题意 有n" role="presentation">nn个站点,排成圆形,每站间距m" role="presentation"> ...

  10. MySQL☞order by与distinct

    asc(升序,默认值)/desc(降序) 1.根据某一列的列值进行升序或者降序操作. select  列名 别名 from 表名 order by 列名 asc/desc 2.根据多个列值进行排序 s ...