求m区间内的最小值

#pragma GCC optimize(3)
#include
using namespace std;
const int maxn=2000001;
int n,a[maxn],m;
struct node {
    int minn,lazy;//minn 维护的最小值,lazy 懒惰标记
} t[maxn<<2];
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        f=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=x*10+ch-48;
        ch=getchar();
    }
    return x*f;
}
inline int lc(int p) {//左孩子 l=2*p;
    return p<<1;
}
inline int rc(int p) {//右孩子 l=2*p+1;
    return p<<1|1;
}
inline void push_up(int p) {
    t[p].minn=min(t[lc(p)].minn,t[rc(p)].minn);//维护父亲节点
}
inline void build(int p,int l,int r) {//建树
    t[p].lazy=0;
    if(l==r) {// 左孩子和右孩子相等,到达最低端,区间最小值就是a[l]
        t[p].minn=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(lc(p),l,mid);//左孩子
    build(rc(p),mid+1,r);//右孩子
    push_up(p);//向上维护父亲节点
}
inline void mark(int p,int k) {//记录当前节点所代表的区间
    t[p].lazy+=k;
    t[p].minn+=k;
}
inline void push_down(int p) {//懒惰标记下放
    mark(lc(p),t[p].lazy);
    mark(rc(p),t[p].lazy);
    t[p].lazy=0;
}
inline void update(int x,int y,int l,int r,int p) {//区间修改
    if(x<=l&&r<=y) {
        mark(p,t[p].lazy);
    }
    push_down(p);
    int mid=(l+r)>>1;
    if(x<=mid) update(x,y,l,mid,p);
    if(y>mid) update(x,y,mid+1,r,p);
    push_up(p);
}
inline int query(int x,int y,int l,int r,int p) {//区间查询
    if(x<=l&&y>=r) {
        return t[p].minn;
    }
    push_down(p);
    int mid=(l+r)>>1;
    if(y<=mid) return query(x,y,l,mid,lc(p));
    else if(x>mid) return query(x,y,mid+1,r,rc(p));
    else return min(query(x,y,l,mid,lc(p)),query(x,y,mid+1,r,rc(p)));
}
int main() {
    scanf("%d%d",&n,&m);
    for(register int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    printf("0\n");//第一个点输出0
    for(register int i=2; i<=n; i++) {
         printf("%d\n",query(i-m>0?i-m:1,i-1,1,n,1));//左区间分两种情况,i-m<0 左区间为1 i-m>0 左区间为i-m
    }
    return 0;
}

希望对各位新学线段树的萌新有帮助

你可能感兴趣的:(题解,线段树)