SHU oj 422 风力观测 线段树
风力观测
发布时间: 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
5 6
1 -1 2 3 -3
1 1 5 1
2 1
2 2
1 2 4 -5
2 2
2 3
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 风力观测 线段树的更多相关文章
- SDUT OJ 数组计算机(线段树)
学长推荐了这个博客详细的介绍了线段树的建立.查找.更新: 数组计算机 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Prob ...
- SDUT OJ 效率至上(线段树)
效率至上 Time Limit: 5000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description 题意很简单,给出一个数目为n ...
- [SCOI2014]方伯伯的OJ(线段树)
方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题.Oj上注册了n个用户,编号为1-n“,一开始他们按照编号排名. 方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为 ...
- 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】
平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...
- 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树
[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- [Swust OJ 746]--点在线上(线段树解法及巧解)
题目链接:http://acm.swust.edu.cn/problem/746/ Time limit(ms): 1000 Memory limit(kb): 65535 fate是一个数学大牛 ...
- [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)
起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...
- 玲珑oj 1117 线段树+离线+离散化,laz大法
1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...
随机推荐
- Lonsdor K518ISE free update news on what makes and year can work
Lonsdor K518ISE engineers recently tested a number of cars and verified working great, below are tes ...
- 在linux中安装memcache服务器
挂载光盘 mkdir -p /media/cdrom mount /dev/cdrom /media/cdrom 设置yum cd /etc/yum.repos.d/ mv CentOS- ...
- 关于Android Camera2 API 的自动对焦的坑
https://www.jianshu.com/p/280e5301b7b9 一.使用.关于Camera2的API使用,参考Google官方的例子: Camera2Basic Camera2Raw C ...
- linux+apache+nginx实现,反向代理动静分离
在我们开发的过程中,一定会遇到,负载均衡方面的问题.下面我们,做一个小例子:使用nginx+apache实现反向代理,动静分离. 这里apache.php.nginx的安装就不做赘述了,不懂的朋友可以 ...
- 在nginx的http模块下面,一个server就可以看做一个站点,配置形式大概是这样的:
http { index index.php index.htm index.html; server { server_name www.site1.com; location / { # [... ...
- 9i时候的块
Header (Common and Variable) The header contains general block information, such as the block addres ...
- Linux使用退格键时出现^H + Tab键命令补全失效/方向键失效 + ls文件夹和文件没有颜色
删除问题 安装kalilinux使用普通用户的的时候按退格键无法实现删除功能 解决的办法有两个 一改变快捷键: 使用Ctrl+Backspace组合键可以实现删除功能 ctrl + backspace ...
- \n和\r区别
转载:https://www.cnblogs.com/hq233/p/6389234.html 符号 ASCII码 意义\n 10 换行NL\r ...
- Navicat Premium 12.0.18安装与激活(转)
转载:https://www.jianshu.com/p/42a33b0dda9c 一.Navicat Premium 12下载 Navicat Premium 12是一套数据库开发管理工具,支持连接 ...
- FireMonkey 源码学习(6)
(6)GetGlyph和GetBaseline TFontGlyphManager是一个抽象类,在不同平台上的实现是不同的,以Windows为例,在FMX.FontGlyphs.Win.pas文件中定 ...