题目描述
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
The array is [1 3 -1 -3 5 3 6 7], and k = 3.
输入输出格式
输入格式:
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
说明
50%的数据,n<=10^5
100%的数据,n<=10^6
思路:
一般人切这道题都用的st表或者是单调队列
我手残打了个线段树(其实是因为我太菜了不会上面两个)
我线段树维护两个值,一个是区间最大值,一个是区间最小值
每次修改,在修改完叶子结点(单点插入,我当做修改处理)后,我向上pushup更新区间最值
每个节点表示的是他所负责的线段的区间最值
查询常规查询即可
代码:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define rii register int i #define rij register int j #define rs 1048576 #define inf 1<<30 using namespace std; struct nod{ long long ma,mi; }x[7000005]; int n,k; void add(long long wz,long long l,long long r,long long val,long long bh) { if(l==r&&l==wz) { x[bh].mi=val; x[bh].ma=val; return; } long long ltt=(l+r)/2; if(wz>ltt) { add(wz,ltt+1,r,val,bh*2+1); } else { add(wz,l,ltt,val,bh*2); } x[bh].mi=min(x[bh*2].mi,x[bh*2+1].mi); x[bh].ma=max(x[bh*2].ma,x[bh*2+1].ma); } struct cs{ int maxn,minx; }ans; cs query(long long l,long long r,long long nl,long long nr,long long bh) { if(l<nl) { l=nl; } if(r>nr) { r=nr; } cs an,bn; an.maxn=-inf; an.minx=inf; bn.maxn=-inf; bn.minx=inf; if(l==nl&&r==nr) { int ltt=x[bh].ma; int kkk=x[bh].mi; an.maxn=ltt; an.minx=kkk; return an; } int ltt=(nl+nr)/2; if(l<=ltt) { an=query(l,r,nl,ltt,bh*2); } if(r>ltt) { bn=query(l,r,ltt+1,nr,bh*2+1); } an.maxn=max(an.maxn,bn.maxn); an.minx=min(an.minx,bn.minx); return an; } long long minn[1000005]; int main() { for(rii=1;i<=7000005;i++) { x[i].ma=-inf; x[i].mi=inf; } scanf("%d%d",&n,&k); for(rii=1;i<=n;i++) { long long ltt; scanf("%lld",<t); add(i,1,rs,ltt,1); } for(rii=1;i<=n-k+1;i++) { ans=query(i,i+k-1,1,rs,1); printf("%d ",ans.minx); minn[i]=ans.maxn; } printf("\n"); for(rii=1;i<=n-k+1;i++) { printf("%d ",minn[i]); } }