【做题笔记】P2251 质量检测

一看题就知道是线段树裸题了。可是,对于每个 (i) ,对应的 (Q) 序列的下标是多少呢?应该查询的区间又是什么呢?

找规律:

(i m)
(1 Rightarrow m)
(2 Rightarrow m+1)
(3 Rightarrow m+2)
(......)
(i Rightarrow m+i-1)

所以需要查找的区间是 ([i,m+i-1])

参考代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#define endl "
"

using namespace std;

int n,m,a[1000010];
struct SegmentTree
{
    int l,r;
    long long data;
    #define l(x) t[x].l
    #define r(x) t[x].r
    #define sum(x) t[x].data
};
SegmentTree t[1000010*40];

inline int read()
{
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}

void build(int p,int l,int r)
{
    l(p)=l,r(p)=r;
    if(l==r){sum(p)=a[l];return ;}
    int mid=(l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    sum(p)=min(sum(p*2),sum(p*2+1));
}

long long ask(int p,int l,int r)
{
    if(l<=l(p)&&r>=r(p))return sum(p);
    int mid=(l(p)+r(p))>>1;
    long long ans=(1<<30);
    if(l<=mid)ans=min(ans,ask(p*2,l,r));
    if(r>mid)ans=min(ans,ask(p*2+1,l,r));
    return ans;
}

int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    for(int i=1;i<=n-m+1;i++)cout<<ask(1,i,m+i-1)<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/BlueInRed/p/12309338.html