嘟嘟嘟




都说这题是送分题,但我怎么就不觉得的呢。

看来我还是太弱了啊……




大体思路就是对于每一个设计方案,答案就是每一个关键点能更新的点的数量之和。

关键在于怎么求一个关键点能更新那些点。




首先这些点肯定是一个包含关键点\(a_i\)的连续区间,于是可以二分找区间的左右端点。

具体是这样的:

对于一个点\(x\),判断这个点能否被\(a_i\)更新。

令\(d = |x - a_i|\),即\(x\)和\(a_i\)间边的数量。然后看从七点出发经过\([x - d, x + d]\)这个区间的所有关键点到\(x\)的距离有没有比\(a_i\)小的,如果没有,就说明\(x\)能被\(a_i\)更新。

这个倒也好理解,按照算法流程,对于每一个关键点,肯定是向两侧的点 一条边一条边更新的,而如果两个关键点同时更新到一个点的话,这个点一定取距离更小的点。




怎么高效的判断呢?也就是怎么快速的求出从起点出发经过一个区间内的所有关键点到指定点的距离的最小值。

首先预处理两点间距离前缀和。

如果\(a_i\)在\(x\)左面,那么这个距离等于\(l[a_i] + sum[x] - sum[a_i] = sum[x] + (l[a_i] - sum[a_i])\);如果在右面,距离就是\(l[a_i] + sum[a_i] - sum[x] = -sum[x] + (l[a_i] + sum[a_i])\)。

发现括号里的两个东西可以用st表维护(或线段树)。代码中是维护了\(l[a_i] + sum[a_i]\)的最小值和\(sum[a_i] - l[a_i]\)的最大值。

还有一个细节在于可能有两个关键点到\(x\)的距离相同,为了防止重复统计,强制规定编号小的点的距离更小。




复杂度\(O(nlog ^ 2n)\),loj上很愉快的过了,某谷上非得开O2。

别忘开long long。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int N = 18;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, m, K;
int lg[maxn];
ll sum[maxn];
struct Edge
{
int p; ll w;
In bool operator < (const Edge& oth)const
{
return p < oth.p;
}
}e[maxn]; ll dis1[maxn], dis2[maxn];
int Min[maxn][N + 2], Max[maxn][N + 2];
In int _min(int a,int b)
{
if(dis1[a] == dis1[b]) return min(a, b);
return dis1[a] < dis1[b] ? a : b;
}
In int _max(int a, int b)
{
if(dis2[a] == dis2[b]) return max(a, b);
return dis2[a] > dis2[b] ? a : b;
}
In void init()
{
sort(e + 1, e + K + 1);
for(int i = 1; i <= K; ++i)
{
dis1[i] = e[i].w + sum[e[i].p], dis2[i] = sum[e[i].p] - e[i].w;
Min[i][0] = Max[i][0] = i;
}
for(int j = 1; (1 << j) <= K; ++j)
for(int i = 1; i + (1 << j) - 1 <= K; ++i)
{
Min[i][j] = _min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);
Max[i][j] = _max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]);
}
}
In int query_Min(int L, int R)
{
int k = lg[R - L + 1];
return _min(Min[L][k], Min[R - (1 << k) + 1][k]);
}
In int query_Max(int L, int R)
{
int k = lg[R - L + 1];
return _max(Max[L][k], Max[R - (1 << k) + 1][k]);
} In int update(int a, int b, int x)
{
ll ans1 = e[a].w + abs(sum[x] - sum[e[a].p]);
ll ans2 = e[b].w + abs(sum[x] - sum[e[b].p]);
if(ans1 ^ ans2) return ans1 < ans2 ? a : b;
int nod1 = abs(e[a].p - x), nod2 = abs(e[b].p - x);
if(nod1 ^ nod2) return nod1 < nod2 ? a : b;
return min(a, b);
}
In bool judge(int x, int t)
{
int d = abs(x - e[t].p), ret = t;
int l = lower_bound(e + 1, e + K + 1, (Edge){x - d, 0}) - e;
int r = upper_bound(e + 1, e + K + 1, (Edge){x + d, 0}) - e - 1;
int mid = upper_bound(e + 1, e + K + 1, (Edge){x, 0}) - e - 1;
if(l <= mid) ret = update(ret, query_Max(l, mid), x);
if(mid < r) ret = update(ret, query_Min(mid + 1, r), x);
return ret == t;
}
In ll solve()
{
ll ret = 0;
for(int i = 1, ansL, ansR; i <= K; ++i)
{
int L = 1, R = e[i].p, mid;
while(L < R)
if(judge(mid = (L + R) >> 1, i)) R = mid;
else L = mid + 1;
ansL = L;
L = e[i].p, R = n;
while(L < R)
if(judge(mid = (L + R + 1) >> 1, i)) L = mid;
else R = mid - 1;
ansR = L;
ret += ansR - ansL + 1;
}
return ret;
} int main()
{
#ifdef mrclr
freopen("t2.in", "r", stdin);
freopen("ha.out", "w", stdout);
#endif
n = read(), m = read();
for(int i = 2; i < maxn; ++i) lg[i] = lg[i >> 1] + 1;
for(int i = 2; i <= n; ++i) sum[i] = read(), sum[i] += sum[i - 1];
for(int i = 1; i <= m; ++i)
{
K = read();
for(int j = 1; j <= K; ++j) e[j].p = read(), e[j].w = read();
init();
write(solve()), enter;
}
return 0;
}

[ZJOI2018]胖的更多相关文章

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

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

  2. 5308: [Zjoi2018]胖

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

  3. P4501 [ZJOI2018]胖

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

  4. zjoi[ZJOI2018]胖

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

  5. ZJOI2018 胖 二分 ST表

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

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

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

  7. BZOJ5308 ZJOI2018胖

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

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

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

  9. bzoj 5308: [Zjoi2018]胖

    Description Cedyks是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公. Cedyks是一个富有的男孩子.他住在著名的ThePLace(宫殿)中. Cedyks是一个 ...

随机推荐

  1. Verification and validation

    Verification Verification is the process to make sure the product satisfies the conditions imposed a ...

  2. hihocoder编程练习赛75

    题目1 : 工作城市分配 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 H公司在北京和上海两个城市各有一间办公室.该公司最近新招募了2N名员工,小Hi负责把这2N名员工 ...

  3. input file图片上传

    <div class="div-title"> <h5>图片上传</h5> <div class="photo-box" ...

  4. Spider-two

    一.网络数据加密:1. md5 / sha1 不可逆加密算法: 结果是十六进制数, 结果不可逆, 多用于文件验证 import hashlib md5_obj = hashlib.md5() sha1 ...

  5. 通过JS生成由字母与数字组合的随机字符串

    在项目中可能需要随机生成字母数字组成的字符,如生成3-32位长度的字母数字组合的随机字符串(位数不固定)或者生成43位随机字符串(位数固定) 使用Math.random()与toString()方法的 ...

  6. CentOS-7.2安装Ambari-2.6.1

    CentOS-7.2安装Ambari-2.6.1 一.Ambari 是什么? Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目, ...

  7. doc命令大全(详细版)

    doc命令大全(详细版) 1 echo 和 @回显命令@                        #关闭单行回显echo off                 #从下一行开始关闭回显@echo ...

  8. NoHttp封装--08 用一个实体类接收所有接口数据

    1.用户信息获取--bean实体类形式返回数据 ①服务器端: 代码: protected void onHandler(HttpServletRequest request, HttpServletR ...

  9. 关于bug的一些思考

    上午看了两道算法,自己编译器上面敲了一遍,然后又去网站上敲了一遍: 编译器上面无论哦如何都调不出来,网站上面也是: 吃个午饭,睡个觉,醒来重新手撸了一遍,然后就过了 : 面对这种事情,真的是自己应该多 ...

  10. gitlab runner安装与使用

    今天来讲一下如何使用gitlab-runner 下载runner,根据自己对应服务器的型号自行选择下载: # Linux x86- sudo wget -O /usr/local/bin/gitlab ...