Time Limit: 30 Sec  Memory Limit: 256 MB

Description

  你有n辆车,分别a1, a2, ..., an位置和n个加油站,分别在b1, b2, ... ,bn 。每个加油站只能支持一辆车的加油,所以你要把这些车开到不同的加油站加油。一个车从x位置开到y位置的代价为 |x-y| ,问如何安排车辆,使得代价之和最小。同时你有q个操作,每次操作会修改第i辆车的位置到x,你要回答每次修改操作之后最优安排方案的总代价。

Input

  第一行一个正整数n,接下来一行n个整数a1, a2, ...,an,接下来一行n个整数b1, b2,... ,bn。
  接下来一行一个正整数q,表示操作的个数。
  接下来q行,每行有两个整数i(1 ≤ i ≤ n)和x,表示将i这辆车开到x位置的操作。
  1 ≤ n, q ≤ 5 * 10^4,所有的车和加油站的范围一直在0到10^9之间。

Output

  共q+1行,第一行表示一开始的最优代价。接下来q行,第i行表示操作i之后的最优代价。

Sample Input

  2
  1 2
  3 4
  1
  1 3

Sample Output

  4
  2
  【样例解释】
  一开始将第一辆车开到位置4,将第二辆车开到位置3,代价为 |4-1|+|3-2|=4。
  修改后第一辆车的位置变成3,代价为 |3-3|+|4-2|=2。

Solution

  一个显然的结论是把a和b排序后按顺序匹配最优,这里就不做说明了。假设我们有一种模拟这个匹配的过程如下:从左到右扫,碰到车就把就把车加入队列,碰到加油站也把加油站加入队列,如果有车和加油站同时在队列中,我们让他们两两匹配,无法匹配我们就拖着所有车或加油站一起向右走。按照这个思路,我们可以这么计算答案:把坐标离散化后,每个车往对应坐标+1,加油站往对应坐标-1,把+1和-1的标记做前缀和,每个坐标的前缀和的绝对值乘上到下一个坐标的距离之和就是答案。那么一次修改就是把这些标记区间+1或-1,同时维护答案。这个可以分块搞,做法如下:按坐标顺序把前缀和分成若干块,每块内把前缀和排序,并求出排序后的每个坐标到排序前的下一个坐标的距离的前缀和,修改时在边缘的块直接暴力重构,剩下整块修改时,标记前缀和大于0和小于0的分开统计答案,排序可以基排桶排啥的,0的分界点也可以动态维护,但我懒所以都写的log,还好能过。总复杂度$O(nlogn\sqrt{n})$或$O(n\sqrt{n})$。

Code

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=x*+c-'';
return x;
}
#define MN 50000
#define MP 150000
#define K 400
int a[MN+],b[MN+],c[MN+],d[MN+];
int p[MP+],pn,s[MP+],ad[K+];
ll ans;
struct data{int s;ll p;}t[MP+];
bool cmp(const data&a,const data&b){return a.s<b.s;}
inline ll z(int x){return x<?-x:x;}
void build(int x)
{
int i;
for(i=x;i<x+K;++i)t[i].s=s[i],t[i].p=p[i];
sort(t+x,t+x+K,cmp);
for(i=x;++i<x+K;)t[i].p+=t[i-].p;
}
void add(int l,int r,int x)
{
int i,lk=(l-)/K,rk=(r-)/K;
for(i=lk*K+;i<=(lk+)*K;++i)s[i]+=ad[lk];ad[lk]=;
for(i=l;i<=r&&i<=(lk+)*K;++i)ans-=z(s[i])*p[i],ans+=z(s[i]+=x)*p[i];
build(lk*K+);
for(i=lk+;i<rk;++i)
{
ad[i]+=x;
int l=i*K+,r=(i+)*K,mid,res=;
if(x<)
{
while(l<=r)
if(t[mid=l+r>>].s+ad[i]<)res=mid,l=mid+;
else r=mid-;
ans+=*t[res].p-t[(i+)*K].p;
}
else
{
while(l<=r)
if(t[mid=l+r>>].s+ad[i]<=)res=mid,l=mid+;
else r=mid-;
ans-=*t[res].p-t[(i+)*K].p;
}
}
if(lk==rk)return;
for(i=rk*K+;i<=(rk+)*K;++i)s[i]+=ad[rk];ad[rk]=;
for(i=r;i>rk*K;--i)ans-=z(s[i])*p[i],ans+=z(s[i]+=x)*p[i];
build(rk*K+);
}
int main()
{
int n=read(),q,i,j;
for(i=;i<=n;++i)p[++pn]=a[i]=read();
for(i=;i<=n;++i)p[++pn]=b[i]=read();
for(q=read(),i=;i<=q;++i)c[i]=read(),p[++pn]=d[i]=read();
sort(p+,p+pn+);
for(i=,j=;i<=pn;++i)if(p[i]!=p[j])p[++j]=p[i];
for(i=j;++i<=pn;)p[i]=;pn=j;
for(i=;i<=n;++i)
++s[a[i]=lower_bound(p+,p+pn+,a[i])-p],
--s[b[i]=lower_bound(p+,p+pn+,b[i])-p];
for(i=;i<=q;++i)d[i]=lower_bound(p+,p+pn+,d[i])-p;
for(i=;i<pn;++i)ans+=z(s[i]+=s[i-])*(p[i]=p[i+]-p[i]);p[i]=;
printf("%lld\n",ans);
for(i=;i<=pn;i+=K)build(i);
for(i=;i<=q;++i)
{
if(a[c[i]]<d[i])add(a[c[i]],d[i]-,-);
else if(d[i]<a[c[i]])add(d[i],a[c[i]]-,);
a[c[i]]=d[i];
printf("%lld\n",ans);
}
}

[BZOJ]4908: [BeiJing2017]开车的更多相关文章

  1. 【BZOJ4908】[BeiJing2017]开车 分块

    [BZOJ4908][BeiJing2017]开车 Description 你有n辆车,分别a1, a2, ..., an位置和n个加油站,分别在b1, b2, ... ,bn .每个加油站只能支持一 ...

  2. [bzoj4908][BeiJing2017]开车

    来自FallDream的博客,未经允许,请勿转载,谢谢. 你有n辆车,分别a1, a2, ..., an位置和n个加油站,分别在b1, b2, ... ,bn .每个加油站只能支持一辆车的加油,所以你 ...

  3. bzoj 4860 [BeiJing2017]树的难题

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4860 题解 点分治 设当前重心为v 假设已经把所有边按照出发点第一关键字, 颜色第二关键字排 ...

  4. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  5. 【BZOJ】【2752】【HAOI2012】高速公路(Road)

    数学期望/线段树 然而又是一道road= =上一道是2750…… 下次不要一看期望题就弃疗么…… 期望题≠不可做题……!! 其实在这题中,期望就是(所有情况下 权值之和)/(总方案数) 因为是等概率抽 ...

  6. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  7. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  8. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  9. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

随机推荐

  1. 掌握SQLServer锁的相关概念

    一.为什么要引入锁 当多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: ◆丢失更新 A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 ◆脏读 ...

  2. Alpha冲刺第十二天

    Alpha冲刺第十二天 站立式会议 项目进展 项目核心功能,如学生基本信息管理模块,学生信用信息模块,奖惩事务管理模块等等都已完成,测试工作大体结束. 问题困难 项目结束后对项目的阶段性总结缺乏一定的 ...

  3. 详谈C++虚函数表那回事(多重继承关系)

    上一篇说了一般继承,也就是单继承的虚函数表,接下来说说多重继承的虚函数表: 1.无虚函数覆盖的多重继承: 代码: #pragma once //无覆盖,多重继承 class Base1 { publi ...

  4. Css之导航栏下拉菜单

    Css: /*下拉菜单学习-2017.12.17 20:17 added by ldb*/ ul{ list-style-type:none; margin:; padding:; overflow: ...

  5. 使用JDBC中的出现的乱码和查询无结果问题

    使用JDBC中的问题 连接的后出现查询结果是乱码. 1.可能是代码的编码与数据库的编码不同 ​ 有可以将二者都设置为UTF-8 2.如果比较懒得话可以只设代码为UTF-8 mysql 连接url中us ...

  6. jquery中attr与prop的区别

    先从一个老生常谈的问题说起,使用jquery实现全选全不选.楼主先使用的jquery版本是 jquery-1.11.1.min.js 全选<input type="checkbox&q ...

  7. Python系列之 - 装饰器

    装饰器主要是用来对函数的操作,我们把定义的函数比作一个蛋糕的话,那么装饰器就是盒子,如果要吃蛋糕就先打开盒子.具体到程序中就是在函数外层又套了一层,套的那一层就是一个装饰器.这么说可能有点抽象,那么我 ...

  8. html标记语言 --文本标记

    html标记语言 --文本标记 二.文本标记 1.h1-h6 标题标记,h1最大 2.font 字体设置标记 2.1 size字体大小.<font size="> 取值范围1-7 ...

  9. @OnetoOne @OnetoMany @ManyToOne(2)

    在班主任(id,name,bjid) 班级(id name) 学生(id name bjid)的 关系中 班主任一对一关联班级 班级一对多关联学生 @OnetoOne @joinColumn(bjid ...

  10. Kotlin技术入门以及和Java对比.md

    一.Kotlin基础环境搭建 Android studio的版本大于3.0 直接支持Kotlin语法,直接创建即可; Android studio的版本小于3.0,步骤如下: 需要下载插件 插件搜索 ...