题目背景

$\frac{1}{4}$遇到了一道水题,$eooooo$完全不会做,于是去请教小$D$。结果小$D$已经去了阿塞拜疆,于是,$\frac{1}{4}$只好来问你,这道题是这样的:


题目描述

在数轴上有一个线段,左端点在$0$,长度为$l$。
现在需要按顺序完成$n$个任务,第$i$个任务可以用$x_i$表示:当线段接触到点$x_i$时,视为完成任务,也就是$x_i$在线段某一端点上、或两端点之间。
你可以任意平移线段,求依次完成任务所需要的最短的平移总距离。
$q$次询问,每次给出一个$l$。


输入格式

从文件$z.in$中读入数据。
第一行,两个自然数$n,q$。
第二行,$n$个整数代表$x_i$。
第三行,$q$个自然数,代表询问的$l$。


输出格式

输出到文件$z.out$中。
输出$q$行,每行一个整数,代表对应询问的答案。


样例

样例输入1:

9 6
2 -3 -1 1 2 3 5 3 7
0 1 2 3 4 5

样例输出1:

21
16
11
10
9
8

样例输入2:

8 8
5 0 5 15 0 -10 0 -20
20 15 14 11 10 5 1 0

样例输出2:

20
20
22
28
30
50
74
80


数据范围与提示

样例$1$解释:

当$l=3$时:
一开始在$[0,3]$,完成任务$1$。
移动到$[−3,0]$,完成任务$2,3$。
移动到$[0,3]$,完成任务$4,5,6$。
移动到$[2,5]$,完成任务$7,8$。
移动到$[4,7]$,完成任务$9$。
$ans=3+3+2+2=10$。

数据范围:

保证$n,q\in [0,10^5],x_i\in [−10^9,10^9],l\in [0,10^9]$。


题解

首先,必须是挨个完成任务,所以如果有一个任务满足$x_{i-1}<x_i<x_{i+1}$或$x_{i-1}>x_i>x_{i+1}$,那么可以删去它。

这样的话,路径肯定是向前走再向后走,于是我们先假设$l=0$,那么答案会是一个一次函数。

那么接着考虑$l\neq 0$,如果$l$不超过最小的位移绝对值时,答案还是一个一次函数;如果超过了的话,我们可以将三个位移合并为一个即可。

将问题离线,利用$map$和$prority_queue$维护即可最小绝对值即可。

代码实现稍复杂u,调了好久……

时间复杂度:$\Theta(n\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int N,Q;
int x[100001];
pair<int,int> l[100001];
map<int,int> mp;
long long sum,ans[100001];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
long long calc(long long x)
{
if(!mp.empty()&&mp.begin()->second<0)return sum-(mp.size()-1)*x;
return sum-mp.size()*x;
}
int main()
{
scanf("%d%d",&N,&Q);
int lst=0;
for(int i=1;i<=N;i++)
{
int a;scanf("%d",&a);
if(a==lst)continue;
if(x[0]&&((x[x[0]]<0&&a<lst)||(x[x[0]]>0&&a>lst)))x[x[0]]+=a-lst;
else x[++x[0]]=a-lst;
lst=a;
}
for(int i=1;i<=Q;i++)
{
scanf("%d",&l[i].first);
l[i].second=i;
}
sort(l+1,l+Q+1);
for(int i=1;i<=x[0];i++)
{
sum+=abs(x[i]);
mp[i]=x[i];
q.push(make_pair(abs(x[i]),i));
}
int t=1;
while(!q.empty())
{
pair<int,int> flag=q.top();q.pop();
auto _=mp.lower_bound(flag.second);
pair<int,int> p=make_pair(_->first,_->second);
if(_==mp.end()||p.first!=flag.second||abs(p.second)!=flag.first)continue;
while(t<=Q&&abs(p.second)>l[t].first)ans[l[t].second]=calc(l[t++].first);
auto begin=mp.begin();
if(p!=make_pair(begin->first,begin->second))
{
auto endle=prev(mp.end());
if(p!=make_pair(endle->first,endle->second))
{
auto pr=prev(_),nx=next(_);
mp.erase(pr);mp.erase(nx);
pair<int,int> pre=make_pair(pr->first,pr->second);
pair<int,int> nxt=make_pair(nx->first,nx->second);
flag.first=p.second;
sum-=abs(p.second);
flag.first+=pre.second;
sum-=abs(pre.second);
flag.first+=nxt.second;
sum-=abs(nxt.second);
_->second=flag.first;
sum+=abs(flag.first);
q.push(make_pair(abs(flag.first),flag.second));
}
else
{
sum-=abs(p.second);
mp.erase(_);
}
}
else
{
if(p.second>0)
{
auto endle=prev(mp.end());
if(p!=make_pair(endle->first,endle->second))
{
auto nx=next(_);mp.erase(nx);
pair<int,int> nxt=make_pair(nx->first,nx->second);
flag.first=p.second;
sum-=abs(p.second);
flag.first+=nxt.second;
sum-=abs(nxt.second);
if(flag.first)
{
_->second=flag.first;
sum+=abs(flag.first);
q.push(make_pair(abs(flag.first),flag.second));
}
else mp.erase(_);
}
else
{
sum-=abs(p.second);
mp.erase(_);
}
}
}
}
while(t<=Q)ans[l[t].second]=calc(l[t++].first);
for(int i=1;i<=Q;i++)printf("%lld\n",ans[i]);
return 0;
}

rp++

[CSP-S模拟测试]:z(模拟+map+小根堆)的更多相关文章

  1. [CSP-S模拟测试]:梦境(贪心+小根堆)

    题目描述 智者奥尔曼曾说过:有缘的人即使相隔海角天涯,也会在梦境中相遇. $IcePrince\text{_}1968$和$IcePrincess\text{_}1968$便是如此.有一天$IcePr ...

  2. 模拟测试—moq:简单一两句

    在Xunit的基础上,说话模拟测试. 假如我们有这样一个控制器里面有这样一个方法,如图 我们在对Bar测试得时候,如果测试未通过,错误有可能来至于Bar,也有可能错误来至于serverde Foo方法 ...

  3. Android单元测试与模拟测试详解

    测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...

  4. [考试反思]1003csp-s模拟测试58:沉淀

    稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...

  5. [考试反思]0729NOIP模拟测试10

    安度因:哇哦. 安度因:谢谢你. 第三个rank1不知为什么就来了.迷之二连?也不知道哪里来的rp 连续两次考试数学都占了比较大的比重,所以我非常幸运的得以发挥我的优势(也许是优势吧,反正数学里基本没 ...

  6. csp-s模拟测试92

    csp-s模拟测试92 关于$T1$:最短路这一定建边最短路. 关于$T2$:傻逼$Dp$这一定线段树优化$Dp$. 关于$T3$:最小生成树+树P+换跟一定是这样. 深入(?)思考$T1$:我是傻逼 ...

  7. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

  8. [开源]微信在线信息模拟测试工具(基于Senparc.Weixin.MP开发)

    目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具 ...

  9. 安装nginx python uwsgi环境 以及模拟测试

    uwsgi帮助文档: http://uwsgi-docs-cn.readthedocs.io/zh_CN/latest/WSGIquickstart.html http://uwsgi-docs.re ...

随机推荐

  1. 上海站赛后总结&反思

    上海站赛后总结&反思 赛后反思一下,本应该做出3~4题的场,最后只出了2题. 先回顾一下比赛,比赛开始10分钟,队友dy就想出了B题是trie树的模板题,然后让mqy码,第一次交的时候有地方打 ...

  2. app自动化appium使用内置adb命令

    一.Appium-server使用 1.登陆页面 高级设置:可以设置Android 和 IOS 日志级别:dabug非常详尽的日志 记录python代码向他发送的请求以及他在收到请求后做的一系列处理 ...

  3. Python3数据科学入门与实践学习教程

      整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的时候可以关注下面几点: 1.为了追求精 ...

  4. 爬虫之Js混淆&加密案例

    需求: 中国空气质量在线监测分析平台是一个收录全国各大城市天气数据的网站,包括温度.湿度.PM 2.5.AQI 等数据,链接为:https://www.aqistudy.cn/html/city_de ...

  5. HDU 1255 覆盖的面积 ( 扫描线 + 离散 求矩阵大于k次面积并 )

    覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. ZOJ 2706 Thermal Death of the Universe

    Thermal Death of the Universe Time Limit: 10 Seconds                                     Memory Limi ...

  7. 牛客练习赛27-----C.水图(DFS求最长路径)

    传送门 来源:牛客网题目描述:小w不会离散数学,所以她van的图论游戏是送分的小w有一张n个点n-1条边的无向联通图,每个点编号为1~n,每条边都有一个长度小w现在在点x上她想知道从点x出发经过每个点 ...

  8. E Easy problem

    链接:https://ac.nowcoder.com/acm/contest/338/E来源:牛客网 Zghh likes number, but he doesn't like writing pr ...

  9. 1233: [Usaco2009Open]干草堆tower

    传送门 感觉正着做不太好搞,考虑倒过来搞 容易想到贪心,每一层都贪心地选最小的宽度,然后发现 $WA$ 了... 因为一开始多选一点有时可以让下一层宽度更小 然后有一个神奇的结论,最高的方案一定有一种 ...

  10. JS-01 书写规范

    此部分内容整理自私教指导和自我体会:(持续更新...) 1.运算符左右两边留空格 (webstorm快捷键ctrl+alt+l): 2.判断值是否相等尽量用“===” 严格等于 : 3.编程中,可有可 ...