题解

很考验思维的一道题

对于不同的任务点,发现如果 \(x_{i-1}<x_i<x_{i+1}\) 或 \(x_{i-1}>x_i>x_{i+1}\) 那么 \(x_i\) 这个位置的数就没用了

将序列先扫一遍,合并不同的位置,然后将合并后的 \(x_i->x_{i+1}\) 按距离排序,再将询问序列从小到大排序,离线询问

用一个 \(map\) 存储所有 \(x_{i}->x_{i+1}\) 的任务编号,二分查找当前点

那么当一个长度大于这段区间了,它就会超出范围,要将它左右的区间和它合并

注意:ans[c[t].id]=calc(ans[c[t].l),t++ 不能写成 ans[c[t].id]=calc(ans[c[t++].l),因为在高版本 c++ 中是从右往左编译的

Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
template<typename T>inline void read(T &x) {
ri f=1;x=0;register char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
x=f?x:-x;
}
}
using IO::read;
namespace nanfeng{
#define node(id,x) (node){id,x}
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
typedef long long ll;
static const int N=1e5+7;
struct node{int id;ll x;}al[N];
inline int operator<(const node &n1,const node &n2) {return n1.x>n2.x;}
inline int cmp(node n1,node n2) {return n1.x<n2.x;}
priority_queue<node> que;
map<int,int> mp;
int n,q,cnt,t=1;
ll sum,dx[N],ans[N];
inline ll calc(ll l) {
if (mp.empty()) return 0;
if (mp.begin()->second<0) return sum-(mp.size()-1)*l;
return sum-mp.size()*l;
}
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
read(n),read(q);
ri lst=0;
for (ri i(1),x;i<=n;p(i)) {
read(x);
if (x==lst) continue;
if (cnt&&(dx[cnt]<0&&x-lst<0||dx[cnt]>0&&x-lst>0)) dx[cnt]+=x-lst;
else dx[p(cnt)]=x-lst;
lst=x;
}
for (ri i(1),l;i<=q;p(i)) read(l),al[i].x=l,al[i].id=i;
sort(al+1,al+q+1,cmp);
for (ri i(1);i<=cnt;p(i)) {
sum+=abs(dx[i]);
mp[i]=dx[i];
que.push(node(i,abs(dx[i])));
}
while(!que.empty()) {
node tmp=que.top();que.pop();
auto it=mp.lower_bound(tmp.id);
if (it==mp.end()) continue;
node nw=node(it->first,it->second);
if (abs(nw.x)!=tmp.x||nw.id!=tmp.id) continue;
while(t<=q&&tmp.x>al[t].x) ans[al[t].id]=calc(al[t++].x);
auto bg=mp.begin();
if (it!=mp.begin()) {
if (it!=prev(mp.end())) {
auto pr=prev(it),nx=next(it);
node tmpr=node(pr->first,pr->second);
node tmpn=node(nx->first,nx->second);
mp.erase(pr);mp.erase(nx);
sum-=abs(nw.x);
sum-=abs(tmpr.x);
sum-=abs(tmpn.x);
tmp.x=nw.x;
tmp.x+=tmpr.x;
tmp.x+=tmpn.x;
it->second=tmp.x;
tmp.x=abs(tmp.x);
sum+=tmp.x;
que.push(tmp);
} else {
sum-=abs(nw.x);
mp.erase(it);
}
} else {
if (nw.x>0) {
if (it!=prev(mp.end())) {
auto nx=next(it);
node tmpn=node(nx->first,nx->second);
mp.erase(nx);
sum-=abs(nw.x);
sum-=abs(tmpn.x);
tmp.x=nw.x;
tmp.x+=tmpn.x;
if (tmp.x) {
it->second=tmp.x;
tmp.x=abs(tmp.x);
sum+=tmp.x;
que.push(tmp);
} else mp.erase(it);
} else {
sum-=abs(tmp.x);
mp.erase(it);
}
}
}
}
while(t<=q) ans[al[t].id]=calc(al[t++].x);
for (ri i(1);i<=q;p(i)) printf("%lld\n",ans[i]);
return 0;
}
}
int main() {return nanfeng::main();}

最新文章

  1. BZOJ1298[SCOI2009]骰子的学问
  2. C 标准库系列之概述
  3. windows系统快捷操作の高级篇
  4. 处理xml c#
  5. jquery 实现邮箱输入自动提示功能:(一)
  6. Makefile 如何轻松搞定
  7. 【转】IOS静态库a文件制作流程
  8. POJ 2126
  9. 源码深度解析SpringMvc请求运行机制(转)
  10. iOS 蒙板,图片叠加显示漏空部分
  11. 日常工作中使用的一些Mongodb语句
  12. HTML之&lt;!DOCTYPE&gt; 标签介绍
  13. oracle数据泵之解决方案(用户)导入导出。
  14. python (3):wxPython打包app,报错
  15. android的编译和运行过程深入分析
  16. How to Type(dp)
  17. win10 安装mingw ruby rails
  18. 基于python的统计公报关键数据爬取
  19. Livereload or meta
  20. SPFA找最大比例环

热门文章

  1. IT面试最全逻辑题,收藏后成功率提高10%
  2. NPOI库读写Excel文件
  3. 「BZOJ2839」集合计数
  4. C语言:模拟密码输入显示星号
  5. sql2008编辑前200行怎么修改
  6. Java基础00-抽象类20
  7. [刘阳Java]_eayui-searchbox搜索组件_第6讲
  8. VS Code 与 ESP32 官方SDK配置
  9. PLICP
  10. Scala学习——函数高级操作