思路:闲来无事补补题,看到这道题貌似是线段树,感觉自己能做出来,在打完初代代码加上无数遍的debug之后,终于让我过了
这题的主要难点在求历史风力最大绝对值,所以要把风力变化的最大值(正方向最大值)和最小值(负方向最大值)记录下来(下面都以最大值最小值来解释)。这里直接单点更新应该是会超时的(我也没试过,不过这种成段更新的,应该是不能这样处理),所以要延迟更新。我这里用lazy来记录风力的变化量,然后用flag标记是否需要向下更新。主要问题就在这个更新上面,这里不只更新了lazy,还更新了当前层变化量的最大值和最小值。
用案例来说明:1 1 5 1(1到5的风力正方向+1)
(节省时间,随意画了一下_(:зゝ∠)_)
在多次更新的时候
更新序号 | 变化值 |
---|---|
1 | -4 |
2 | 2 |
3 | -1 |
4 | 15 |
5 | -4 |
比如最大值出现在第四次更新,当发生延迟更新时,1和2先更新,所以lazy=-2,maxw=0,minw=-4;
3和4更新的lazy=14,maxw=14,minw=-1。
3和4合并的更新再向下更新就是lazy=-2+14 , maxw=max(0,-2+14) , minw=min(-4,-2+(-1))
更新的具体实现如下面代码
void updatelazy(int t)//更新
{
p[t*2].flag=p[t*2+1].flag=true;//标记需要向下更新
p[t*2].maxw=max(p[t*2].maxw,p[t].maxw+p[t*2].lazy);
p[t*2+1].maxw=max(p[t*2+1].maxw,p[t].maxw+p[t*2+1].lazy);
p[t*2].minw=min(p[t*2].minw,p[t].minw+p[t*2].lazy);
p[t*2+1].minw=min(p[t*2+1].minw,p[t].minw+p[t*2+1].lazy);
p[t*2].lazy+=p[t].lazy;
p[t*2+1].lazy+=p[t].lazy;
p[t].flag=false;
p[t].maxw=p[t].minw=p[t].lazy=0;
}
感觉解释不清楚。。。还是先看代码吧
等我想清楚了再更新
下面是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
struct point{
int l,r;
int maxw,minw;
int lazy;
bool flag;
}p[N*4];
int n,q;
int a[N];
void build(int t,int l,int r)
{
p[t].l=l;
p[t].r=r;
p[t].maxw=p[t].minw=p[t].lazy=0;
p[t].flag=false;
if(l==r)
return;
int mid=(l+r)/2;
build(t*2,l,mid);
build(t*2+1,mid+1,r);
}
void updatelazy(int t)
{
p[t*2].flag=p[t*2+1].flag=true;
p[t*2].maxw=max(p[t*2].maxw,p[t].maxw+p[t*2].lazy);
p[t*2+1].maxw=max(p[t*2+1].maxw,p[t].maxw+p[t*2+1].lazy);
p[t*2].minw=min(p[t*2].minw,p[t].minw+p[t*2].lazy);
p[t*2+1].minw=min(p[t*2+1].minw,p[t].minw+p[t*2+1].lazy);
p[t*2].lazy+=p[t].lazy;
p[t*2+1].lazy+=p[t].lazy;
p[t].flag=false;
p[t].maxw=p[t].minw=p[t].lazy=0;
}
void update(int t,int l,int r,int lazy)
{
int lc=p[t].l;
int rc=p[t].r;
int mid=(lc+rc)/2;
if(lc>=l&&rc<=r)
{
p[t].flag=true;
p[t].lazy+=lazy;
p[t].maxw=max(p[t].maxw,p[t].lazy);
p[t].minw=min(p[t].minw,p[t].lazy);
return;
}
if(p[t].flag)
updatelazy(t);
if(mid>=r) update(t*2,l,r,lazy);
else if(mid<l) update(2*t+1,l,r,lazy);
else update(2*t,l,mid,lazy),update(2*t+1,mid+1,r,lazy);
}
int query(int t,int x)
{
int lc=p[t].l;
int rc=p[t].r;
int mid=(lc+rc)/2;
if(lc==rc)
return max(abs(p[t].maxw+a[x]),abs(p[t].minw+a[x]));
if(p[t].flag)
updatelazy(t);
if(mid>=x) return query(t*2,x);
else return query(2*t+1,x);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
while(q--)
{
int type,x,y,z;
scanf("%d",&type);
if(type==1)
{
scanf("%d%d%d",&x,&y,&z);
update(1,x,y,z);
}
else
{
scanf("%d",&x);
printf("%d\n",query(1,x));
}
}
}
}