bzoj 5308: [Zjoi2018]胖
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]胖的更多相关文章
- 5308: [Zjoi2018]胖
5308: [Zjoi2018]胖 链接 分析: 题目转化为一个点可以更新多少个点,一个点可以更新的点一定是一个区间,考虑二分左右端点确定这个区间. 设当前点是x,向右二分一个点y,如果x可以更新到y ...
- BZOJ 5308 [ZJOI2018] Day2T2 胖 | 二分 ST表
题目链接 LOJ 2529 BZOJ 5308 题解 这么简单的题 为什么考场上我完全想不清楚 = = 对于k个关键点中的每一个关键点\(a\),二分它能一度成为哪些点的最短路起点(显然这些点在一段包 ...
- 【BZOJ5308】[ZJOI2018]胖(模拟,ST表,二分)
[BZOJ5308][ZJOI2018]胖(模拟,ST表,二分) 题面 BZOJ 洛谷 题解 首先发现每条\(0\)出发的边都一定会更新到底下的一段区间的点. 考虑存在一条\(0\rightarrow ...
- P4501 [ZJOI2018]胖
题目 P4501 [ZJOI2018]胖 官方口中的送分题 做法 我们通过手玩(脑补),\(a_i\)所作的贡献(能更新的点)为:在\(a_i\)更新\(\forall x\)更新前前没有其他点能把\ ...
- bzoj 5212: [Zjoi2018]历史
Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有n个城市,这n个城市被恰好n?1条双向道路联通,即任意两个城 ...
- [ZJOI2018]胖
嘟嘟嘟 都说这题是送分题,但我怎么就不觉得的呢. 看来我还是太弱了啊-- 大体思路就是对于每一个设计方案,答案就是每一个关键点能更新的点的数量之和. 关键在于怎么求一个关键点能更新那些点. 首先这些点 ...
- zjoi[ZJOI2018]胖
题解: 因为n,m很大 所以复杂度应该是和m相关的 考虑到每个点的影响区间是连续的 就很简单了 区间查询最小值线段树维护(st表也可以) 然后注意一下不要重复算一个就可以了 max函数用templat ...
- ZJOI2018 胖 二分 ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/ZJOI2018Day2T2.html 题目传送门 - BZOJ5308 题目传送门 - LOJ2529 题目传送 ...
- 2019.03.04 bzoj5308: [Zjoi2018]胖(二分答案+st表)
传送门 想题5分钟调题两小时系列 其实还是我tcl 读完题之后自然会知道一个关键点能够更新的点是一段连续的区间,于是我们对于每个点能到的左右区间二分答案,用ststst表维护一下查询即可. 代码: # ...
随机推荐
- java中容器的概念
容器:顾名思义,装东西的器物至于spring中bean,aop,ioc等一些都只是实现的方式具体容器哪些值得我们借鉴,我个人觉得是封装的思想.将你一个独立的系统功能放到一个容器之中,可以当做一个大的接 ...
- mybatis 学习笔记(一):mybatis 初认识
mybatis 学习笔记(一):mybatis 初认识 简介 MyBatis是一个Java持久层框架,它通过XML描述符或注解把对象与存储过程或SQL语句关联起来.mybatis 可以将 prepar ...
- python基础之内置函数(一)
内建函数都在 _builtins_ 里面 (1)abs() 取绝对值 adb(-10) 10 (2)bool()将参数转换成布尔型,返回值是True或False 参数是数字时,0返回False,其他任 ...
- 封装的一个sorted_vector示例,实现了stl::set的一部分接口
STL set能保证最坏情况下的查找和插入效率,logN.但是维护红黑树开销较大.set内的元素按照一定的逻辑顺序组织,查找.插入等操作的结果都和排序规则有关. 适合STL ...
- 【洛谷2113】看球泡妹子 DP背包
看球泡妹子 题目背景 2014年巴西世界杯开幕了,现在满城皆是世界杯,商家们利用它大赚一笔,小明和小红也借此机会增进感情. 题目描述 本届世界杯共有\(N\)支球队,\(M\)场比赛.男球迷小明喜欢看 ...
- 华为敏捷/DevOps实践:产品经理如何开好迭代计划会议
大家好,我是华为云DevCloud项目管理服务的产品经理恒少,作为布道师和产品经理,出差各地接触客户是常态,线下和华为云的客户交流.布道.技术沙龙. 但是线下交流,覆盖的用户总还是少数.我希望借助线上 ...
- c3中基本动画
动画:是CSS3中具有颠覆性的特征之一,可通过设置多个节点来精确控制一个或一组动画,常用来实现复杂的动画效果:. 必要元素: a.通过@keyframes指定动画序列:自动补间动画,确定两个点,系统会 ...
- 190310HTML&CSS&JS
一.HTML 1.web server import socket def handle_request(client): buf = client.recv(1024) client.send(by ...
- sqoop常用语句
1,列出全部数据库 sqoop list-databases --connect jdbc:sqlserver://10.10.10.2 --username sa --password 1 2,导 ...
- 【转】intellij idea使用指南—— 导入Eclipse的Web项目
通常一个团队中可能有人用eclipse,有人用intelliJ,那么经常会出现需要导入别人用eclipse建好的web项目.而IntelliJ提供了多种项目类型的导入方式,其中就有eclipse. 在 ...