风力观测
发布时间: 2017年7月9日 20:20 最后更新: 2017年7月10日 21:12 时间限制: 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
这题的难点在于如何向下更新改变的值,不能直接改变下放,这样会影响时间顺序,但是可以每次下放的时候先下放最大最小值,然后这个父区间的最大最小值,就是历史的对子区间影响最大的最大最小值,下放到子区间就是对子区间最大的改变,也就是 x是tr的子节点,tr[x].minn=tr[rt].minn+tr[x].now,这就是历史最大改变值。。maxx也一样,更新完以后就可以更新 now的值了 tr[x].now+=tr[rt].now; 这就消除了要提前下放的影响,因为这样已经把提前能到的最大最小值存起来,最后要把父节点的最大最小和当前值都清空。不然多次下放怎么办。= =(更新的l,r是不用变的,我傻逼了,一直wa)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100100;
struct node
{
int minn,maxx,now;
}tr[maxn<<2];
struct EE
{
int l,r,nu;
}E[maxn<<2];
int num[maxn];
void pushdown(int x)
{
tr[x<<1].maxx=max(tr[x<<1].maxx,tr[x].maxx+tr[x<<1].now);
tr[x<<1].minn=min(tr[x<<1].minn,tr[x].minn+tr[x<<1].now);
tr[x<<1|1].maxx=max(tr[x<<1|1].maxx,tr[x].maxx+tr[x<<1|1].now);
tr[x<<1|1].minn=min(tr[x<<1|1].minn,tr[x].minn+tr[x<<1|1].now);
tr[x<<1].now+=tr[x].now;
tr[x<<1|1].now+=tr[x].now;
tr[x].maxx=tr[x].minn=tr[x].now=0;
}
void build(int rt,int l,int r)
{
tr[rt].minn=0;
tr[rt].maxx=tr[rt].now=0;
E[rt].l=l;
E[rt].r=r;
if(l==r)
{
E[rt].nu=num[l];
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void update(int rt,int l,int r,int b)
{
if(E[rt].l>=l&&E[rt].r<=r)
{
tr[rt].now+=b;
tr[rt].minn=min(tr[rt].minn,tr[rt].now);
tr[rt].maxx=max(tr[rt].maxx,tr[rt].now);
return ;
}
pushdown(rt);
int mid=(E[rt].l+E[rt].r)>>1;
if(l<=mid) update(rt<<1,l,r,b);
if(r>mid) update(rt<<1|1,l,r,b);
}
int query(int rt,int d)
{
if(E[rt].l==E[rt].r&&E[rt].l==d)
{
return max(abs(E[rt].nu+tr[rt].maxx),abs(E[rt].nu+tr[rt].minn));
}
pushdown(rt);
int mid=(E[rt].l+E[rt].r)>>1;
if(d<=mid) return query(rt<<1,d);
if(d>mid) return query(rt<<1|1,d);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
build(1,1,n);
while(q--)
{
int d;
scanf("%d",&d);
if(d==1)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
update(1,l,r,x);
}
else
{
int x;
scanf("%d",&x);
printf("%d\n",query(1,x));
}
}
}
}