「ZJOI2018」胖(ST表+二分)

不开 \(O_2\) 又没卡过去是种怎么体验。。。

这可能是 \(ZJOI2018\) 最简单的一题了。。。我都能 \(A\)。。。

首先我们发现这个奇怪的图每个点扩展的是一个区间 \([L,R]\),然后我们就可以二分端点了。

一个点 \(x\) 扩展到点 \(y\) 至少要 \(|x-y|\) 的时间,所以我们把 \(a_i\) 排个序,在上面二分一个合法的区间使得 \(|x-a_l|\leq t\) 且 \(|x-a_r|\leq t\)

然后若能扩展到 \(y\),那么 \(0\) 号点到 \(y\) 号点的距离为 \(|dis_y-dis_x|+l\)。我们用两个 \(ST\) 表把绝对值拆掉,分别维护最小值即可。

时间复杂度 \(O(n\log^2 n)\)

为什么 \(dl\) 出题人会出到 \(2\times 10^5\)。。。两个 \(\log\) 一般只出到 \(10^5\) 的啊。。。

\(Code\ Below:\)

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200000+10;
int n,m,k,w[maxn],lg[maxn];ll dis[maxn]; struct node{
int p;ll l;
node(int p=0,ll l=0):p(p),l(l){}
}a[maxn];
inline bool operator < (const node &a,const node &b){
return a.p<b.p;
} struct Sparse_Table{
ll st[maxn][18];
inline void init(){
for(int i=1;i<=k;i++) st[i][0]=a[i].l;
for(int j=1;j<=lg[k];j++)
for(int i=1;i+(1<<j)-1<=k;i++) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
inline ll query(int l,int r){
l=max(l,1);r=min(r,n);
l=lower_bound(a+1,a+k+1,node(l))-a;
r=upper_bound(a+1,a+k+1,node(r))-a-1;
if(l>r) return 1e18;
int k=lg[r-l+1];
return min(st[l][k],st[r-(1<<k)+1][k]);
}
}L,R; inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
} inline bool check1(int x,int y){
// (2*y-x,y,x]
if(x==y) return 1;
ll a=L.query(2*y-x+1,y)+dis[y];
ll b=R.query(y,x-1)-dis[y];
ll c=R.query(x,x)-dis[y];
if(a<=c||b<=c) return 0;
if(2*y-x>=1) return L.query(2*y-x,2*y-x)+dis[y]>=c;
return 1;
} inline bool check2(int x,int y){
// [x,y,2*y-x)
if(x==y) return 1;
ll a=L.query(x+1,y)+dis[y];
ll b=R.query(y,2*y-x-1)-dis[y];
ll c=L.query(x,x)+dis[y];
if(a<=c||b<=c) return 0;
if(2*y-x<=n) return R.query(2*y-x,2*y-x)-dis[y]>c;
return 1;
} inline int solve1(int x){
int l=1,r=x,mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(check1(x,mid)) r=mid-1,ans=mid;
else l=mid+1;
}
return ans;
} inline int solve2(int x){
int l=x,r=n,mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(check2(x,mid)) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
} int main()
{
n=read(),m=read();
for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
for(int i=2;i<=n;i++){
w[i]=read();
dis[i]=dis[i-1]+w[i];
}
ll ans;
while(m--){
k=read();
for(int i=1;i<=k;i++) a[i].p=read(),a[i].l=read();
sort(a+1,a+k+1);ans=0;
for(int i=1;i<=k;i++) a[i].l-=dis[a[i].p];L.init();
for(int i=1;i<=k;i++) a[i].l+=2*dis[a[i].p];R.init();
for(int i=1;i<=k;i++) ans+=solve2(a[i].p)-solve1(a[i].p)+1;
printf("%lld\n",ans);
}
return 0;
}

「ZJOI2018」胖(ST表+二分)的更多相关文章

  1. Loj #2529. 「ZJOI2018」胖

    Loj #2529. 「ZJOI2018」胖 题目描述 Cedyks 是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公. Cedyks 是一个富有的男孩子.他住在著名的 The P ...

  2. 「ZJOI2018」历史

    「ZJOI2018」历史 前置知识 \(\text{LCT}\) 维护子树信息,考虑辅助树上一个节点的子树信息只是其代表的这一段链的信息,设 \(S(u)\) 为节点 \(u\) 的子树信息,那么在辅 ...

  3. 「ZJOI2018」历史(LCT)

    「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...

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

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

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

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

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

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

  7. hdu5289 ST表+二分

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

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

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

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

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

随机推荐

  1. leetcode312

    class Solution { public int maxCoins(int[] iNums) { int[] nums = new int[iNums.length + 2]; int n = ...

  2. @RestController 与 @Controller @RequestMapping("/") 区别很大

    后者可以通过返回字符串,返回到指定路径的html http://localhost:8080/  这样显示 ,但是仍以get方式请求的. https://www.cnblogs.com/zgqys19 ...

  3. python学习Day1 计算机原理编程思维

    一.学习思想:3W+1H   学什么(what).为什么学(why).用在哪里(where).怎么用(how) 学习编程语言重在代码量.代码量.代码量! 二.计算机五大组成部分,三大核心: 五大组成部 ...

  4. Sqlite安装教程

    Sqlite下载页面:http://www.sqlite.org/download.html Windows安装 需要下载 sqlite-tools-win32-*.zip 和 sqlite-dll- ...

  5. 服务器&linux

    linux vsftp查看端口占用:netstat -natp |grep 21如果有占用21端口进程,kill它 ,或者remove它.安装:yum -y install vsftpduseradd ...

  6. MariaDB ColumnStore初探(1):安装、使用及测试

    相信大家在对接BI数据报表部门有很深刻的体验,高大上的复杂SQL关联JOIN十几张表在InnoDB里跑起来,会让你酸爽到死.它的出现正是解决这个问题,DBA能不能轻松愉快地玩耍,就要靠它了,“神州行我 ...

  7. Unity 2018 By Example 2nd Edition

    Unity is the most exciting and popular engine used for developing games. With its 2018 release, Unit ...

  8. Block学习总结

    最近网上浏览了一些关于Block的文章,自己进行一下消化吸收. Void (^blockName)(parma)-> Block声明 Void (^) (parma){};  ->Bloc ...

  9. fortitoken

    1.token状态为error,且不能分配给用户使用 解决: 关联有User的token状态是error的原因是:用户一直并未使用.

  10. java基础 ----- 选择结构

    ---------    流程控制 ------     流程图 ------   基本的  if  选择结构 import java.util.Scanner; public class GetPr ...