嘟嘟嘟




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

看来我还是太弱了啊……




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

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




首先这些点肯定是一个包含关键点\(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. js 金额补全处理

    function returnFloat(value) { var value = Math.round(parseFloat(value) * 100) / 100; var xsd = value ...

  2. jQuery效果之jQuery实现图片的依次加载图片

    css代码: ;;} ul#portfolio li{float: left;margin:0 5px 0 0;width:250px;height: 250px;list-style: none;} ...

  3. 51nod1238 最小公倍数之和 V3(莫比乌斯反演)

    题意 题目链接 Sol 不想打公式了,最后就是求一个 \(\sum_{i=1}^n ig(\frac{N}{i})\) \(g(i) = \sum_{i=1}^n \phi(i) i^2\) 拉个\( ...

  4. 简析服务端通过geotools导入SHP至PG的方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在浏览器端直接上传SHP后服务端进行数据的自动入PG ...

  5. VirtualBox网络连接方式

    VirtualBox图形界面下有四种网络接入方式,它们分别是: 1.NAT 网络地址转换模式(NAT,Network Address Translation) 2.Bridged Adapter 桥接 ...

  6. 口碑点餐相关问题FAQ

    1.菜品上传中:出现重复错误或者违禁词 检查并修改商家中心本次上传中的重复菜品,或者删除口碑掌柜以及第三方平台已添加的重复菜品(重复菜品临时快捷办法:修改菜品名称) 2.手持pos 打开自动接单,无响 ...

  7. Scala视图界定

    package big.data.analyse.dataSet /** * 视图界定 * Created by zhen on 2018/11/29. */ /*class Pair_NotPerf ...

  8. django CharField按整形排序

    #models.py from django.db import models class Block(models.Model): ... height = models.CharField(max ...

  9. mysql----SELECT names/zh

    < SELECT names   Language: English  • 中文 name continent Afghanistan Asia Albania Europe Algeria A ...

  10. c#判断两个对象和对象中的属性是否相同(以及记录对象中的哪些字段,和详细的改变情况)

    当前项目需要记录变更记录,即用户在进行编辑后,将变更操作记录下来.但是数据没有发生变化,则不记录. 代码1:(仅仅返回是否变化的标识) /// <summary> /// 反射对比实体属性 ...