一看题就知道是线段树裸题了。可是,对于每个 \(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
#include
#include
#define endl "\n"
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<