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

题面

BZOJ

洛谷

题解

首先发现每条\(0\)出发的边都一定会更新到底下的一段区间的点。

考虑存在一条\(0\rightarrow x\)的边,我们来求解其可以影响的区间\([L,R]\),显然\(L\le x\le R\)。

两侧分开考虑,以左边举例。

二分一个\(L\)。如果这个\(L\)可行,即不存在一条边\(0\rightarrow y\),满足\(W_{0\rightarrow x}+Dis(L,x)\ge W_{0\rightarrow y}+Dis(L,y)\),且\(abs(y-L)\le abs(x-L)\)。

也就是要么\(x\)出发能够更新最短路,要么就是\(x\)离\(L\)更近,所以先被\(x\)的路径更新了一次。

那么对于二分出来的\(L\),令\(len=|x-L|\),如果在\([L-len,L+len]\)区间内存在一个点能够更新出更小的距离则当前\(L\)不可行。\(R\)同理。

然后大力\(ST\)表二分一下就好了。

注意一下如果一个点可以同时被多个点更新的时候,一定要确定好一个顺序关系,使得最终计算出来的结果不重不漏。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 200200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,Q,k,lg[MAX];
ll w[MAX],v1[MAX],v2[MAX];
ll mn[20][MAX],mx[20][MAX];
struct Line{int x,w;}a[MAX];
bool operator<(Line a,Line b){return a.x<b.x;}
int Max(int x,int y)
{
if(v1[x]!=v1[y])return v1[x]>v1[y]?x:y;
if(a[x].x!=a[y].x)return a[x].x>a[y].x?x:y;
return x<y?x:y;
}
int Min(int x,int y)
{
if(v2[x]!=v2[y])return v2[x]<v2[y]?x:y;
if(a[x].x!=a[y].x)return a[x].x<a[y].x?x:y;
return x<y?x:y;
}
void pre()
{
for(int i=1;i<=k;++i)
v1[i]=w[a[i].x]-a[i].w,v2[i]=w[a[i].x]+a[i].w;
for(int i=1;i<=k;++i)mx[0][i]=mn[0][i]=i;
for(int j=1;j<=lg[k];++j)
for(int i=1;i+(1<<j)-1<=k;++i)
{
mx[j][i]=Max(mx[j-1][i],mx[j-1][i+(1<<(j-1))]);
mn[j][i]=Min(mn[j-1][i],mn[j-1][i+(1<<(j-1))]);
}
}
ll RMQ_mx(int l,int r)
{
int k=lg[r-l+1];
return Max(mx[k][l],mx[k][r-(1<<k)+1]);
}
ll RMQ_mn(int l,int r)
{
int k=lg[r-l+1];
return Min(mn[k][l],mn[k][r-(1<<k)+1]);
}
bool check(int x,int l,int y)
{
int p=lower_bound(&a[1],&a[k+1],(Line){y-l,0})-a;
int q=upper_bound(&a[1],&a[k+1],(Line){y+l,0})-a-1;
int r=lower_bound(&a[1],&a[k+1],(Line){y,0})-a;
if(r<=q)
{
int pos=RMQ_mn(r,q);ll V=abs(w[a[x].x]-w[y])+a[x].w;
if(v2[pos]-w[y]<V||(v2[pos]-w[y]==V&&abs(a[pos].x-y)<abs(a[x].x-y))
||(v2[pos]-w[y]==V&&abs(a[pos].x-y)==abs(a[x].x-y)&&pos<x))
return false;
}
if(p<r)
{
int pos=RMQ_mx(p,r-1);ll V=abs(w[a[x].x]-w[y])+a[x].w;
if(w[y]-v1[pos]<V||(w[y]-v1[pos]==V&&abs(a[pos].x-y)<abs(y-a[x].x))
||(w[y]-v1[pos]==V&&abs(a[pos].x-y)==abs(a[x].x-y)&&pos<x))
return false;
}
return true;
}
int GetL(int x)
{
int l=1,r=a[x].x,ret=a[x].x;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(x,a[x].x-mid,mid))ret=mid,r=mid-1;
else l=mid+1;
}
return ret;
}
int GetR(int x)
{
int l=a[x].x,r=n,ret=a[x].x;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(x,mid-a[x].x,mid))ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
ll Solve()
{
k=read();for(int i=1;i<=k;++i)a[i].x=read(),a[i].w=read();
sort(&a[1],&a[k+1]);
pre();ll ans=0;
for(int i=1;i<=k;++i)
{
ans+=GetR(i)-GetL(i)+1;
}
return ans;
}
int main()
{
n=read();Q=read();
for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
for(int i=2;i<=n;++i)w[i]=read()+w[i-1];
while(Q--)printf("%lld\n",Solve());
return 0;
}

【BZOJ5308】[ZJOI2018]胖(模拟,ST表,二分)的更多相关文章

  1. 洛谷P4501/loj#2529 [ZJOI2018]胖(ST表+二分)

    题面 传送门(loj) 传送门(洛谷) 题解 我们对于每一个与宫殿相连的点,分别计算它会作为多少个点的最短路的起点 若该点为\(u\),对于某个点\(p\)来说,如果\(d=|p-u|\),且在\([ ...

  2. 「ZJOI2018」胖(ST表+二分)

    「ZJOI2018」胖(ST表+二分) 不开 \(O_2\) 又没卡过去是种怎么体验... 这可能是 \(ZJOI2018\) 最简单的一题了...我都能 \(A\)... 首先我们发现这个奇怪的图每 ...

  3. BZOJ5308 ZJOI2018胖

    贝尔福特曼(?)的方式相当于每次将所有与源点直接相连的点的影响区域向两边各扩展一格.显然每个点在过程中最多更新其他点一次且这些点构成一段连续区间.这个东西二分st表查一下就可以了.注意某一轮中两点都更 ...

  4. 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分

    4310: 跳蚤 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 180  Solved: 83[Submit][Status][Discuss] De ...

  5. BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...

  6. hdu5289 ST表+二分

    用裸的St表+暴力枚举查询时稳TLE的,可以枚举每个区间的起点+二分满足条件的区间右端,这样复杂度是O(nlogn) #include<iostream> #include<cstr ...

  7. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  8. 2016多校联合训练1 D题GCD (ST表+二分)

    暑假颓废了好久啊...重新开始写博客 题目大意:给定10w个数,10w个询问.每次询问一个区间[l,r],求出gcd(a[l],a[l+1],...,a[r])以及有多少个区间[l',r']满足gcd ...

  9. GCD(st表+二分)

    GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  10. ZSTU 4241 圣杯战争(ST表+二分)

    题目链接  ZSTU 4241 问题转化为有很多区间,现在每次给定一个区间求这个区间和之前所有区间中的某一个的交集的最大长度. 强制在线. 首先我们把所有的区间预处理出来. 然后去重(那些被包含的小区 ...

随机推荐

  1. Git push提交时报错Permission denied(publickey)...Please make sure you have the correct access rights and the repository exists.

    一.git push origin master 时出错 错误信息为: Permission denied(publickey). fatal: Could not read from remote ...

  2. eclipse如何添加web dynamic project

    很多eclipse版本是不能直接新建web dynamic project的,需要从网上找插件或更新. 比较方便的是在Help → Install-New-Software,点击add按钮,在Loca ...

  3. 【kindle笔记】之 《黑客微百科》-2018-6-17

    前段时间复习六级的时候,从图书馆看到一本书,然后带回来了.今天开始读.今天是2018年6月17日. 严格来讲,一本不算kindle笔记的笔记,不过广义的啃豆笔记了解一下.哈哈. 首页说到的黑客理念是: ...

  4. PAT L3-020 至多删三个字符

    https://pintia.cn/problem-sets/994805046380707840/problems/994805046946938880 给定一个全部由小写英文字母组成的字符串,允许 ...

  5. 【Python3练习题 019】 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。

    后一个分数的分子=前一个分数的分子+分母,后一个分数的分母=前一个分数的分子,循环个20次就有结果.注意,假设分子为a,分母为b,虽然 a = a + b, 但此时a已经变成 a+b 了,所以再给b重 ...

  6. Bootstrap知识记录:表格和按钮

    基本格式.table3.带边框的表格//给表格增加边框<table class="table table-bordered">4.悬停鼠标//让<tbody> ...

  7. Bootstrap 字体图标(Glyphicons)

    http://www.runoob.com/bootstrap/bootstrap-glyphicons.html 什么是字体图标? 字体图标是在 Web 项目中使用的图标字体.虽然,Glyphico ...

  8. 深浅copy详解

    一. 前言 在python中,对象的赋值和深浅copy,是有差异的.最终得的值也不同,下面我们就通过几个例子,来看下它们之间的区别. 二. 赋值 list2 = ["jack",2 ...

  9. 为什么js中要用void 0 代替undefined

    这个是Backbone.js中的一句源码 if (callback !== void 0 && 'context' in opts && opts.context == ...

  10. Hbase存储流程