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. ubuntu14.04,安装Gnome 15.10 (桌面)

    Linux:ubuntu14.04 Gnome:15.10 更新最新版Gnome的一个好处:更新了ubuntu的软件源,我们可以使用ubuntu的软件中心获取更多需要的软件!! ubuntu默认的桌面 ...

  2. NSCalendar日历

    前言 NSCalendar 对世界上现存的常用的历法进行了封装,既提供了不同历法的时间信息,又支持日历的计算. NSCalendar -- 日历类,它提供了大部分的日期计算接口,并且允许您在NSDat ...

  3. 【转载】Java资源大全中文版

    Java资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-java 就是 akullpp 发起维护的 Java 资源列表,内容 ...

  4. 【转】C#控件——DataGridView单元格文本自动换行

    源地址:https://www.cnblogs.com/wangshenhe/archive/2012/07/25/2608324.html DataGridView是.NET开发中常用的控件,在开发 ...

  5. oracle闪回存储过程

    源地址:https://www.baidu.com/link?url=qgVCi_BLGOYqxJN0Fqqt-9N0SmCwtGI70SIh-TFpx1nP6oaVoMj8H6yjEqilto6TM ...

  6. django 实现电子支付功能

    思路:调用第三方支付 API 接口实现支付功能.本来想用支付宝来实现第三方网站的支付功能的,但是在实际操作中发现支付宝没有 Python 接口,网上虽然有他人二次封装的的 Python 接口,但是对我 ...

  7. Communication with each role instance in Azure

    Use WCF  Communication with role instance in azure 1)In worker role build WCF Service public overrid ...

  8. Python数组(二)

    一.函数list 可将任何序列(如字符串)作为list的参数.list实际上是一个类,而不是函数. test=['java','C#','C','C++'] print(list(test)) ——& ...

  9. 设置placeholder的样式

    :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #f00; } ::-moz-placeholder { /* Mozilla Fir ...

  10. Codeforces Round #162 (Div. 2) A~D 题解

    A. Colorful Stones (Simplified Edition) time limit per test 2 seconds memory limit per test 256 mega ...