Loj3033 JOISC 2019 Day2两个天线

下午唯一听懂的题目但,但还是比较模糊.写一篇题解来加深一下印象.

题目大意:给定\(n\)根天线,第\(i\)跟天线的高度为\(h_i\),切它能和与他距离在\([a_i,b_i]\)内的天线交流.

两根天线互相交流当且仅当他们彼此都在对方的交流范围内.定义两根天线交流的代价为\(|H_i-H_j|\)

有\(Q\)次询问,每次询问区间\([l,r]\)内所有够相互交流的天线的交流代价的最大值(\(n <= 2*10^5\))

首先看到这种东西,我的第一反应是CDQ分治,但是CDQ分治不好处理这种多组区间询问的问题

所以只能另想办法

发现如果我们对于每个\(j\),都去寻找前面的一个\(i\)去和它匹配的话.那么\(j\)在\(i\)的影响范围内当且仅当\(j\in[i+a_i,i+b_i]\)

也就是说,我们要想办法让\(i\)在\(i+a_i\)处开始有贡献,在\(i + b_i + 1\)处失去贡献.这就会想到线段树扫描线,我们每个节点维护一个\(c_i\),当我们枚举到\(i+a_i\)时,就讲线段树上第\(i\)个位置的\(c_i\)变为\(h_i\),当离开这个区间时,就将其变为\(-\infty\)

这样我们就处理好了第一个问题:如何确保\(j\)在\(i\)的交流范围内

接下来看第二个问题,如何确保\(i\)在\(j\)的范围内并且统计答案

首先,\(|h_i-h_j|\)这个东西,我们可以讲它拆成\(h_i-h_j\)和\(h_j-h_i\)就好了我们只考虑\(h_i-h_j\),另一个可以将值域翻转来考虑.

那么我们设\(d_i\)表示第\(i\)的天线和右边的匹配的最大代价这个东西可以直接在线段树上维护

而.\(di=h_i+max(-h_j)\)

那么我们对于每个\(j\),它能影响的之前的区间是\([i - b_i,i-a_i]\)(特判一下负数)

我们在在线段树上维护一个\(tag\),表示\(max(-hj)\)

那么扫到\(j\)时,就相当于在\([i - b_i,i-a_i]\)的\(tag\)和\(-h_j\)取max,这也是线段树能完成的

最后对于每个查询,扫到\(r_i\)时计算\([l_i,r_i]\)的答案就好了

(SB的我\(n,m\)不分WA了一晚上)

#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
#include<cctype>
#include<algorithm>
#define pii pair<int,int>
#define mk make_pair
using namespace std;
const int N = 5e5 + 3;
const int INF = 1e9 + 7;
int n,m,t;
struct node{
int lc,rc;
int d,c,tag;
}a[N << 1];
struct U{
int hi;
int ai,bi;
}b[N];
struct Q{
int li,ri;
}q[N];
int ans[N];
vector <pii> G1[N];
vector <int> G2[N];
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
inline void pushup(int u){
a[u].c = max(a[a[u].lc].c,a[a[u].rc].c);
a[u].d = max(a[a[u].lc].d,a[a[u].rc].d);
}
inline void build(int u,int l,int r){
a[u].c = a[u].d = a[u].tag = -INF;
if(l == r) return ;
int mid = (l + r) >> 1;
a[u].lc = ++t;build(a[u].lc,l,mid);
a[u].rc = ++t;build(a[u].rc,mid + 1,r);
// pushup(u);
}
inline void pushdown(int u,int l,int r){
if(a[u].tag == -INF) return;
a[a[u].lc].tag = max(a[a[u].lc].tag,a[u].tag);
a[a[u].rc].tag = max(a[a[u].rc].tag,a[u].tag);
a[a[u].lc].d = max(a[a[u].lc].d,a[a[u].lc].c + a[a[u].lc].tag);
a[a[u].rc].d = max(a[a[u].rc].d,a[a[u].rc].c + a[a[u].rc].tag);
a[u].tag = -INF;
}
inline void change(int u,int l,int r,int x,int v){
if(l == r){
a[u].tag = -INF;
a[u].c = v;
//a[u].d = max
return;
}
pushdown(u,l,r);
int mid = (l + r) >> 1;
if(x <= mid) change(a[u].lc,l,mid,x,v);
else change(a[u].rc,mid + 1,r,x,v);
pushup(u);
}
inline void updata(int u,int l,int r,int ll,int rr,int v){
if(l == ll && r == rr){
a[u].tag = max(a[u].tag,v);
a[u].d = max(a[u].d,a[u].c + a[u].tag);
return ;
}
pushdown(u,l,r);
int mid = (l + r) >> 1;
if(rr <= mid) updata(a[u].lc,l,mid,ll,rr,v);
else if(ll > mid) updata(a[u].rc,mid + 1,r,ll,rr,v);
else {
updata(a[u].lc,l,mid,ll,mid,v);
updata(a[u].rc,mid + 1,r,mid + 1,rr,v);
}
pushup(u);
}
inline int query(int u,int l,int r,int ll,int rr){
if(l == ll && r == rr) return a[u].d;
pushdown(u,l,r);
int mid = (l + r) >> 1;
if(rr <= mid) return query(a[u].lc,l,mid,ll,rr);
else if(ll > mid) return query(a[u].rc,mid + 1,r,ll,rr);
else return max(query(a[u].lc,l,mid,ll,mid),
query(a[u].rc,mid + 1,r,mid + 1,rr));
}
inline void work(){
t = 1;
build(1,1,n);
for(int i = 1;i <= n;++i){
for(int j = 0;j < G1[i].size();++j)
change(1,1,n,G1[i][j].first,G1[i][j].second?b[G1[i][j].first].hi:-INF);
if(i - b[i].ai > 0) updata(1,1,n,max(1,i - b[i].bi),i - b[i].ai,-b[i].hi);
for(int j = 0;j < G2[i].size();++j)
ans[G2[i][j]] = max(ans[G2[i][j]],query(1,1,n,q[G2[i][j]].li,q[G2[i][j]].ri));
}
}
int main(){
n = read();
for(int i = 1;i <= n;++i){
b[i].hi = read(),b[i].ai = read(),b[i].bi = read();
if(i + b[i].ai <= n) G1[i + b[i].ai].push_back(mk(i,1));
if(i + b[i].bi + 1 <= n) G1[i + b[i].bi + 1].push_back(mk(i,0));
}
m = read();
for(int i = 1;i <= m;++i){
q[i].li = read();
q[i].ri = read();
G2[q[i].ri].push_back(i);
}
for(int i = 1;i <= m;++i) ans[i] = -1;
work();
// for(int i = 1;i <= n;++i) printf("%d\n",ans[i]);
for(int i = 1;i <= n;++i) b[i].hi = 1000000001 - b[i].hi;
work();
for(int i = 1;i <= m;++i) printf("%d\n",ans[i]);
return 0;
}

Loj3033 JOISC 2019 Day2两个天线的更多相关文章

  1. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  2. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  3. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  4. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  5. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  6. 「JOISC 2019 Day3」穿越时空 Bitaro

    「JOISC 2019 Day3」穿越时空 Bitaro 题解: ​ 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. ​ 问题变成二维平面上 ...

  7. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  8. CEOI 2019 Day2 T2 魔法树 Magic Tree (LOJ#3166、CF1993B、and JOI2021 3.20 T3) (启发式合并平衡树,线段树合并)

    前言 已经是第三次遇到原题. 第一次是在 J O I 2021 S p r i n g C a m p \rm JOI2021~Spring~Camp JOI2021 Spring Camp 里遇到的 ...

  9. day2——两数相加

    // 小白一名,0算法基础,艰难尝试算法题中,若您发现本文中错误, 或有其他见解,往不吝赐教,感激不尽,拜谢. 领扣 第2题 今日算法题干//给定两个非空链表来表示两个非负整数.位数按照逆序方式存储, ...

随机推荐

  1. js单选按钮的默认值

    function SelectWindow(str) { initradio('PhysiotherapyOptionsTable.Sex',sex);       } function initra ...

  2. C# 获取上传文件的文件名和后缀名

    //获得要上传的文件 HttpPostedFile file = Request.Files[]; //获得到文件名 string fileName = System.IO.Path.GetFileN ...

  3. Maximum Depth of Binary Tree 树的最大深度

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...

  4. phpexcel使用说明5----ThinkPHP+PHPExcel[导入][导出]实现方法

    转自:http://www.thinkphp.cn/code/403.html实现步骤: 注意:phpexcel必须是1.78版本的,不能用1.8以上的 一:去官网http://phpexcel.co ...

  5. JPA使用nativequery多表关联查询返回自定义实体类

    本文为JPA的学习采坑,如有问题欢迎指正. JPA官方推荐的多表关联查询使用不便,接触的有些项目可能会使用JPA 做简单查询,Mybaits做复杂查询.所以想要寻找一种好用的解决方案. JPA多表关联 ...

  6. LeetCode54 Spiral Matrix

    题目: Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spira ...

  7. @codeforces - 1187F@ Expected Square Beauty

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个序列 x = {x1, x2, ..., xn},已知 ...

  8. 模板—Kruskal

    int getf(int x){return (f[x]==x)?x:f[x]=getf(f[x]);} void hb(int x,int y){x=getf(x),y=getf(y),f[y]=x ...

  9. uva 11665 Chinese Ink (几何+并查集)

    UVA 11665 随便给12的找了一道我没做过的几何基础题.这题挺简单的,不过uva上通过率挺低,通过人数也不多. 题意是要求给出的若干多边形组成多少个联通块.做的时候要注意这题是不能用double ...

  10. hdu 3934 Summer holiday (凸包+旋转卡壳)

    Problem - 3934 晚上为了演示给师弟看水平序的凸包是多么的好写,于是就随便找了一题凸包,25min居然1y掉了.. 代码如下: #include <cmath> #includ ...