Description

Cedyks是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公。

Cedyks是一个富有的男孩子。他住在著名的ThePLace(宫殿)中。

Cedyks是一个努力的男孩子。他每天都做着不一样的题来锻炼他的The SaLt(灵魂)。

这天,他打算在他的宫殿外围修筑一道城墙,城墙上有n座瞭望塔。

你可以把城墙看做一条线段,瞭望塔是线段上的n个点,其中1和n分别为城墙的两个端点。

其中第i座瞭望塔和第i+1座瞭望塔的距离为wi,他们之间的道路是双向的。

城墙很快就修建好了,现在Cedyks开始计划修筑他的宫殿到城墙的道路。

因为这题的题目名称,

Cedyks打算用他的宫殿到每一个瞭望塔的最短道路之和来衡量一个修建计划。

现在Cedyks手上有m个设计方案,第k个设计方案会在宫殿和瞭望塔之间修建Tk条双向道路,

第i条道路连接着瞭望塔ai,长度为Li。

计算到每一个瞭望塔的最短路之和是一个繁重的工程,本来Cedyks想用广为流传的SPFA算法

来求解,但是因为他的butter(缓冲区)实在是太小了,他只能转而用原始的贝尔福特曼算法

来计算,算法的流程大概如下:

1:定义宫殿是0号点,第i个瞭望塔是i号点,双向边(ui,vi,Li)为一条连接ui和vi的双向道路。

令d为距离数组,最开始d0=0,di=10^18(i∈[1,n])。

2:令辅助数组c=d。依次对于每一条边(ui,vi,wi)进行增广,

cui=min(cui,dvi+wi),

cvi=min(cvi,dui+wi)。

3:令t为c和d中不一样的位置个数,即令S={i|ci!=di},则t=S。若t=0,说明d

就是最终的最短路,算法结束。否则令d=c,回到第二步。

因为需要计算的设计方案实在是太多了,所以Cedyks雇佣了一些人来帮他进行计算。

为了避免这些人用捏造出来的数据偷懒,他定义一个设计方案的校验值为在这个方案

上运行贝尔福特曼算法每一次进入第三步t的和。他会让好几个雇佣来的人计算同样

的设计方案,并比对每一个人给出的校验值。

你是Cedyks雇佣来的苦力之一,聪明的你发现在这个情形下计算最短路的长度的和

是一件非常简单的事情。但是寄人篱下不得不低头,你不得不再计算出每一个方案

的校验值来交差。

Solution

考场上不会判一个点相同时间被相同距离更新多次的情况...

只需要考虑关键点能够更新到的点就可以了

显然能更新到的点是一个区间

二分这个左右端点

如何判断一个点 \(y\) ,能否被关键点 \(x\) 更新?

设 \(d=|x-y|\)

判断 \([y-d,y+d]\) 之间是否存在其他的关键点到 \(y\) 的距离更小

分别考虑 \(y\) 左右两边的情况:

以左边为例,设可以更新 \(y\) 的点为 \(p\),\(w\) 为到 \(1\) 的距离:

要查找 \(w[x]-w[p]+l\) 的最小值,维护一个 \(max(w[p]-l)\) 即可

注意当两个关键点同时可以更新一个点的时候,要以更新的时间为第二关键字,编号为第三关键字

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
typedef long long ll;
const int N=2e5+10;
int n,Q,m,L[N],R[N],mx,Log[N],sx[N][20],sd[N][20];ll w[N],v1[N],v2[N];
struct data{int x,l;}a[N];
inline bool operator <(data i,data j){return i.x<j.x;}
inline int Max(int p,int q){
if(v1[p]!=v1[q])return v1[p]>v1[q]?p:q;
if(a[p].x!=a[q].x)return a[p].x>a[q].x?p:q;
return p<q?p:q;
}
inline int Min(int p,int q){
if(v2[p]!=v2[q])return v2[p]<v2[q]?p:q;
if(a[p].x!=a[q].x)return a[p].x<a[q].x?p:q;
return p<q?p:q;
}
inline void build(){
mx=Log[m]+1;
for(int i=1;i<=m;i++){
sd[i][0]=i,sx[i][0]=i;
v1[i]=w[a[i].x]-a[i].l,v2[i]=w[a[i].x]+a[i].l;
}
for(int j=1;j<=mx;j++)
for(int i=1;i+(1<<j)-1<=m;i++){
int k=i+(1<<(j-1));
sd[i][j]=Max(sd[i][j-1],sd[k][j-1]);
sx[i][j]=Min(sx[i][j-1],sx[k][j-1]);
}
}
inline ll qx(int l,int r){
int k=Log[r-l+1];
return Min(sx[l][k],sx[r-(1<<k)+1][k]);
}
inline ll qd(int l,int r){
int k=Log[r-l+1];
return Max(sd[l][k],sd[r-(1<<k)+1][k]);
}
inline bool check(int x,int d,int y){
int p=lower_bound(a+1,a+m+1,(data){y-d,0})-a;
int q=upper_bound(a+1,a+m+1,(data){y+d,0})-a-1;
int z=lower_bound(a+1,a+m+1,(data){y,0})-a;
if(q>=z){
int t1=qx(z,q);ll vr=abs(w[y]-w[a[x].x])+a[x].l;
if(v2[t1]-w[y]<vr || (v2[t1]-w[y]==vr && abs(a[t1].x-y)<abs(y-a[x].x)))return false;
if(v2[t1]-w[y]==vr && abs(a[t1].x-y)==abs(y-a[x].x) && t1<x)return false;
}
if(p<z){
int t1=qd(p,z-1);ll vr=abs(w[y]-w[a[x].x])+a[x].l;
if(w[y]-v1[t1]<vr || (w[y]-v1[t1]==vr && abs(a[t1].x-y)<abs(y-a[x].x)))return false;
if(w[y]-v1[t1]==vr && abs(a[t1].x-y)==abs(y-a[x].x) && t1<x)return false;
}
return true;
}
inline int getL(int x){
int l=1,r=a[x].x,mid,ret=r;
while(l<=r){
mid=(l+r)>>1;
if(check(x,a[x].x-mid,mid))ret=mid,r=mid-1;
else l=mid+1;
}
return ret;
}
inline int getR(int x){
int l=a[x].x,r=n,mid,ret=l;
while(l<=r){
mid=(l+r)>>1;
if(check(x,mid-a[x].x,mid))ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
inline void solve(){
gi(m);
for(int i=1;i<=m;i++)gi(a[i].x),gi(a[i].l);
sort(a+1,a+m+1);
build();
ll ans=0;
for(int i=1;i<=m;i++)L[i]=getL(i),R[i]=getR(i),ans+=R[i]-L[i]+1;
printf("%lld\n",ans);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>Q;
for(int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
for(int i=2;i<=n;i++)gi(w[i]),w[i]+=w[i-1];
while(Q--)solve();
return 0;
}

bzoj 5308: [Zjoi2018]胖的更多相关文章

  1. 5308: [Zjoi2018]胖

    5308: [Zjoi2018]胖 链接 分析: 题目转化为一个点可以更新多少个点,一个点可以更新的点一定是一个区间,考虑二分左右端点确定这个区间. 设当前点是x,向右二分一个点y,如果x可以更新到y ...

  2. BZOJ 5308 [ZJOI2018] Day2T2 胖 | 二分 ST表

    题目链接 LOJ 2529 BZOJ 5308 题解 这么简单的题 为什么考场上我完全想不清楚 = = 对于k个关键点中的每一个关键点\(a\),二分它能一度成为哪些点的最短路起点(显然这些点在一段包 ...

  3. 【BZOJ5308】[ZJOI2018]胖(模拟,ST表,二分)

    [BZOJ5308][ZJOI2018]胖(模拟,ST表,二分) 题面 BZOJ 洛谷 题解 首先发现每条\(0\)出发的边都一定会更新到底下的一段区间的点. 考虑存在一条\(0\rightarrow ...

  4. P4501 [ZJOI2018]胖

    题目 P4501 [ZJOI2018]胖 官方口中的送分题 做法 我们通过手玩(脑补),\(a_i\)所作的贡献(能更新的点)为:在\(a_i\)更新\(\forall x\)更新前前没有其他点能把\ ...

  5. bzoj 5212: [Zjoi2018]历史

    Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有n个城市,这n个城市被恰好n?1条双向道路联通,即任意两个城 ...

  6. [ZJOI2018]胖

    嘟嘟嘟 都说这题是送分题,但我怎么就不觉得的呢. 看来我还是太弱了啊-- 大体思路就是对于每一个设计方案,答案就是每一个关键点能更新的点的数量之和. 关键在于怎么求一个关键点能更新那些点. 首先这些点 ...

  7. zjoi[ZJOI2018]胖

    题解: 因为n,m很大 所以复杂度应该是和m相关的 考虑到每个点的影响区间是连续的 就很简单了 区间查询最小值线段树维护(st表也可以) 然后注意一下不要重复算一个就可以了 max函数用templat ...

  8. ZJOI2018 胖 二分 ST表

    原文链接https://www.cnblogs.com/zhouzhendong/p/ZJOI2018Day2T2.html 题目传送门 - BZOJ5308 题目传送门 - LOJ2529 题目传送 ...

  9. 2019.03.04 bzoj5308: [Zjoi2018]胖(二分答案+st表)

    传送门 想题5分钟调题两小时系列 其实还是我tcl 读完题之后自然会知道一个关键点能够更新的点是一段连续的区间,于是我们对于每个点能到的左右区间二分答案,用ststst表维护一下查询即可. 代码: # ...

随机推荐

  1. spring @Async 线程池使用

    最近公司项目正逐渐从dubbo向springCloud转型,在本次新开发的需求中,全部使用springcloud进行,在使用时线程池,考虑使用spring封装的线程池,现将本次使用心得及内容记录下来 ...

  2. Promise超时情况

    export const ERROR_PROMISE_TIMEOUT = 'ERROR_PROMISE_TIMEOUT'; export default function (promise, time ...

  3. 灯塔AOI简易实现

    首先我们来讨论下游戏开发中的几个坐标系,为了方便解释,我截取了灯塔AOI DEMO当NPC数目为0时候的样子(代码地址觉得有帮助的童鞋记得给我代码点个星^_^) 先对这张图简单说明下: 蓝色的坐标轴表 ...

  4. 如何处理html中的内联元素之间水平空隙

    写HTML时把需要紧挨着的内联元素写在一行,设置其父容器的font-size为0,再设置内联元素的字体大小,例如: <!DOCTYPE html> <html lang=" ...

  5. ajax-3验证

    $("#formBtn").click(function () { // var regName =/^[\u4e00-\u9fa5]{2,10}$/;//姓名只能是汉字切2-10 ...

  6. C语言实现数组及链表的快速排序

    1. 数组快排: 方法一: #include <stdio.h> #include <stdlib.h> //交换 void swap(int *pi, int *pj) { ...

  7. hadoop集群配置方法---mapreduce应用:xml解析+wordcount详解---yarn配置项解析

    注:以下链接均为近期hadoop集群搭建及mapreduce应用开发查找到的资料.使用hadoop2.6.0,其中hadoop集群配置过程下面的文章都有部分参考. hadoop集群配置方法: ---- ...

  8. 一款很好用的页面滚动元素动画插件-AOS.JS

    aos.js是一款效果超赞的页面滚动元素动画jQuery动画库插件.该动画库可以在页面滚动时提供28种不同的元素动画效果,以及多种easing效果.在页面往回滚动时,元素会恢复到原来的状态. 加载方法 ...

  9. 图像金字塔、高斯金字塔、差分金字塔(DOG金字塔)、尺度空间、DoG (Difference of Gaussian)角点检测

    [图像金字塔] 图像金字塔是一种以多分辨率来解释图像的结构,通过对原始图像进行多尺度像素采样的方式,生成N个不同分辨率的图像.把具有最高级别分辨率的图像放在底部,以金字塔形状排列,往上是一系列像素(尺 ...

  10. PHP 生成 MySql 数据库字典

    项目说明 通过配置 MySql 数据库信息,使用 PHP 生成数据表字典可以输出在当前页面,可以生成文件保存在指定位置,也可以下载格式支持网页HTML格式.CSV格式(Excel 读取).ZIP压缩格 ...