风力观测

发布时间: 2017年7月9日 18:17   最后更新: 2017年7月9日 21:04   时间限制: 1000ms   内存限制: 128M

描述

小Y正在观测y地区的风力情况,他在一条直线上依此设定了n个观测点,并观测与直线垂直方向的风力值,风力有时是正向的也有时是反向的,规定正向时的风力值为正数,他发现每次风力值的变化都可以表示为观测点上一条线段[L,R]上的同时增强或者减弱。小Y希望能够实时统计这些观测点的数据,并且实时分析这些观测点在历史中到达的风力最大绝对值,但是他无法同时对大量的观测点进行分析, 更重要的是他记不住这些观测点过去的风力大小,于是他希望你来用计算机帮助他完成这个任务。

你简化了这个问题,将问题分为两种查询:

1.对观测点[L,R]上的风力正向增强X。(X为负数表示正向减弱,即反向加强)

2.查询观测点A上的历史风力最大绝对值。

输入

第一行有一个整数T表示数据组数。(T<=10)
接着有T组数据,每组数据第一行是整数n和q,表示观测点个数和查询次数。
第二行有n个数a1,...,an,表示每个观测点的风力初始值。
接着有q行,表示q次操作,格式为:
1 L R X:表示对[L,R]线段上的正向风力同时增强x。
2 A:表示查询A点的历史风力最大绝对值。
1<=n,q<=100000。
1<=L,R,A<=n
−10000<=ai, X<=10000

输出

对每次询问2,输出一个数字表示风力值并换行。

样例输入1 复制

1
5 6
1 -1 2 3 -3
1 1 5 1
2 1
2 2
1 2 4 -5
2 2
2 3
样例输出1

2
1
5
3

题目链接:http://acmoj.shu.edu.cn/problem/422/

官方题解有注释

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
#define mid (L+R)/2
#define ls 2*rt
#define rs 2*rt|1
#define lson ls,L,mid
#define rson rs,mid+1,R
const int mx = 1e5+;
typedef pair<int,int> P;
int MAX[mx<<],MIN[mx<<],lazy[mx<<];
int a[mx];
int n,m;
void push_down(int rt){
MAX[ls] = max(MAX[ls],MAX[rt]+lazy[ls]);
MIN[ls] = min(MIN[ls],MIN[rt]+lazy[ls]);
MIN[rs] = min(MIN[rs],MIN[rt]+lazy[rs]);
MAX[rs] = max(MAX[rs],MAX[rt]+lazy[rs]); //因为上面的lazy已经更新过了所以再给下面用一遍会重复所以不只要增加还未更新的即可
lazy[rs] += lazy[rt];
lazy[ls] += lazy[rt];
lazy[rt] = MAX[rt] = MIN[rt] = ;
}
void update(int rt,int L,int R,int l,int r,int v){
if(l<=L && R <= r){
lazy[rt]+=v;
MAX[rt] = max(MAX[rt],lazy[rt]); //这一段如果没有被更新过就是直接这样
MIN[rt] = min(MIN[rt],lazy[rt]); //如果这一段被更新过的话再更新的时候只要取历史的最高还是一样的结果
return;
}
if(MAX[rt]||MIN[rt]||lazy[rt]) //如果其中有一个不为0那就更新
push_down(rt);
if(l>mid) update(rson,l,r,v);
else if(r<=mid) update(lson,l,r,v);
else{
update(rson,mid+,r,v);
update(lson,l,mid,v);
}
}
P query(int rt,int L,int R,int x){
if(L == R && L == x)
return {MAX[rt],MIN[rt]};
if(MAX[rt]||MIN[rt]||lazy[rt])
push_down(rt);
if(x > mid) return query(rson,x);
else return query(lson,x);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(MAX,,sizeof(MAX));
memset(MIN,,sizeof(MIN));
memset(lazy,,sizeof(lazy));
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i++)
scanf("%d",&a[i]);
while(m--){
int casei;
scanf("%d",&casei);
if(casei == ){
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
update(,,n,l,r,v);
}
else{
int x;
scanf("%d",&x);
P ans = query(,,n,x);
printf("%d\n",max(abs(a[x]+ans.first),abs(a[x]+ans.second)));
}
}
}
return ;
}

另一种写法:

对于每颗线段树都是一时间为节点,而不是以原来的每个点为点,;

每个点对应一颗线段树,这颗线段树是以时间为点,进行更新;

巧妙的是,对于区间更新的方式,是从上一颗线段树继承下去的,有点可持久化的意思;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define eps 1e-14
#define bug(x) cout<<"bug"<<x<<endl;
const int N=1e5+,M=2e6+,inf=1e9+;
const LL INF=1e18+,mod=1e9+; struct SGT
{
int maxx[N<<],minn[N<<],lazy[N<<];
void pushup(int pos)
{
maxx[pos]=max(maxx[pos<<],maxx[pos<<|]);
minn[pos]=min(minn[pos<<],minn[pos<<|]);
}
void pushdown(int pos)
{
if(lazy[pos])
{
maxx[pos<<]+=lazy[pos];
maxx[pos<<|]+=lazy[pos];
lazy[pos<<]+=lazy[pos];
lazy[pos<<|]+=lazy[pos];
minn[pos<<]+=lazy[pos];
minn[pos<<|]+=lazy[pos];
lazy[pos]=;
}
}
void build(int l,int r,int pos)
{
lazy[pos]=minn[pos]=maxx[pos]=;
if(l==r)return;
int mid=(l+r)>>;
build(l,mid,pos<<);
build(mid+,r,pos<<|);
}
void update(int L,int R,int c,int l,int r,int pos)
{
if(L<=l&&r<=R)
{
maxx[pos]+=c;
minn[pos]+=c;
lazy[pos]+=c;
return;
}
pushdown(pos);
int mid=(l+r)>>;
if(L<=mid)update(L,R,c,l,mid,pos<<);
if(R>mid)update(L,R,c,mid+,r,pos<<|);
pushup(pos);
}
pair<int,int> query(int L,int R,int l,int r,int pos)
{
if(L<=l&&r<=R)return make_pair(minn[pos],maxx[pos]);
pushdown(pos);
int mid=(l+r)>>;
int maxx=-inf,minn=inf;
if(L<=mid)
{
pair<int,int> le=query(L,R,l,mid,pos<<);
maxx=max(maxx,le.second);
minn=min(minn,le.first);
}
if(R>mid)
{
pair<int,int> ri=query(L,R,mid+,r,pos<<|);
maxx=max(maxx,ri.second);
minn=min(minn,ri.first);
}
return make_pair(minn,maxx);
}
}tree;
int a[N],ans[N];
vector<pair<int,int> >v[N];
vector<int>qq[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=; i<=n; i++)
scanf("%d",&a[i]),v[i].clear(),qq[i].clear();
for(int i=;i<=q;i++)
{
ans[i]=inf*;
int t;
scanf("%d",&t);
if(t==)
{
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
v[l].push_back(make_pair(i,val));
if(r+<=n)v[r+].push_back(make_pair(i,-val));
}
else
{
int val;
scanf("%d",&val);
qq[val].push_back(i);
}
}
tree.build(,q,);
for(int i=;i<=n;i++)
{
for(int j=;j<v[i].size();j++)
tree.update(v[i][j].first,q,v[i][j].second,,q,);
for(int j=;j<qq[i].size();j++)
{
pair<int,int> out=tree.query(,qq[i][j],,q,);
//cout<<out.first<<" "<<out.second<<endl;
ans[qq[i][j]]=max(abs(a[i]),max(abs(a[i]+out.first),abs(a[i]+out.second)));
}
}
for(int i=;i<=q;i++)
if(ans[i]<inf*)
printf("%d\n",ans[i]);
}
return ;
}

SHU oj 422 风力观测 线段树的更多相关文章

  1. SDUT OJ 数组计算机(线段树)

    学长推荐了这个博客详细的介绍了线段树的建立.查找.更新: 数组计算机 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Prob ...

  2. SDUT OJ 效率至上(线段树)

    效率至上 Time Limit: 5000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description 题意很简单,给出一个数目为n ...

  3. [SCOI2014]方伯伯的OJ(线段树)

    方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题.Oj上注册了n个用户,编号为1-n“,一开始他们按照编号排名. 方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为 ...

  4. 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】

    平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...

  5. 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树

    [BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...

  6. luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树

    LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...

  7. [Swust OJ 746]--点在线上(线段树解法及巧解)

    题目链接:http://acm.swust.edu.cn/problem/746/ Time limit(ms): 1000 Memory limit(kb): 65535   fate是一个数学大牛 ...

  8. [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)

    起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...

  9. 玲珑oj 1117 线段树+离线+离散化,laz大法

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

随机推荐

  1. vue:vue-resource

    vue-resource是一个非常轻量的用于处理HTTP请求的插件,它提供了两种方式来处理HTTP请求: 使用Vue.http或this.$http: 使用Vue.resource或this.$res ...

  2. ORM for Net主流框架汇总

    ORM框架:Object/Relation Mapping(对象/关系 映射)的缩写,易于理解的模型化数据的方法.简单的说就是把数据库的关系型数据类型转换为用对象型程序控制的框架类型. 框架优缺点分析 ...

  3. sass中的循环判断条件语句

    @if $lte7:true !default;//是否兼容ie6,7 //inline-block //ie6-7 *display: inline;*zoom:1; @mixin inline-b ...

  4. kali linux DIY

    开启你的kali linux DIY之旅 感谢原博主的分享,真的非常非常受用! 更新源 首先 是kali2016.2更新源的问题,网上找了好久,都不是很满意.后来把kali 2016.2安装到实体机中 ...

  5. Python3 实现 JS 中 RSA 加密的 NoPadding 模式

    前因后果之哗啦啦废话连篇: 这几天本人在 Python 做某网站登陆的时候,发现其登陆时用户名和密码被加密了 F12 仔细看了一下,发现是调用了一个 js 的 rsa 加密库,页面 dom 中有 rs ...

  6. Vue小案例 之 商品管理------删除商品与提示

    实现删除商品功能 根据索引来进行删除商品: 实现删除商品的HTML: <!--显示表格--> <div class="table-warp"> <di ...

  7. Spring Boot(一):入门篇

    Spring Boot(一):入门篇 一.Spring Boot介绍 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程. 该框架 ...

  8. 【题解】 P2234 [HNOI2002]营业额统计

    平衡树板题 原题传送门 这道题要用Splay,我博客里有对Splay的详细介绍 这道题目还算比较模板的 每输入一个数,先不要插入 要求一下前驱和后继与x差的最小值并加到答案中 再把x插入平衡树 然后你 ...

  9. topcoder srm 706 div1

    1.给定一个迷宫,点号表示不可行,井号表示可行.现在可以改变其中的一些井号的位置.问最少改变多少个井号可以使得从左上角到右下角存在路径. 思路:设高为$n$,宽为$m$,若井号的个数$S$小于$n+m ...

  10. Flutter第1天--初始分析+Dart方言+Canvas简绘 - 云+社区

    Flutter第1天--初始分析+Dart方言+Canvas简绘 - 云+社区 - 腾讯云 https://cloud.tencent.com/developer/article/1378974