2017金马五校赛 M.风力观测(线段树)

题目传送门

思路:闲来无事补补题,看到这道题貌似是线段树,感觉自己能做出来,在打完初代代码加上无数遍的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));
            }
        }
    }
} 

猜你喜欢

转载自blog.csdn.net/cyf199775/article/details/75042237