acwing 滑動視窗:
單調對列好久之前就學了,但是一直沒有深刻理解,這次又學了一下,感覺理解了點,就寫篇部落格記錄一下。三種解題**:滑動視窗這題是個經典的題,可以用線段樹寫,但**量有點大,而且使用空間比較大,如果卡空間的話,顯然線段樹是過不去的,rmq在洛谷上好像是不能寫,倍增的思想可以水過時間,但這題卻過不了空間,倍增比線段樹的空間大了幾倍,所以這題過不去。
rmq:acwing 上可以
#include.h>
using namespace std;
#define ll long
long
const
int maxn=
1e6;
ll n,m;
ll dma[maxn][10
],dmi[maxn][10
];ll a[maxn]
;void
init()
for(ll j=1;
(1<<=m; j++)}
}ll rmq_max
(ll l,ll r)
ll rmq_min
(ll l,ll r)
intmain()
init()
;for
(ll i=
1; m+i-
1<=n; i++)}
for(ll i=
1; m+i-
1<=n;i++)}
}
線段樹:
#include
#include
#include
using namespace std;
const
int maxn=
1e6+5;
int a[maxn]
;struct node
tr[maxn*4]
;void
pushup
(int k)
void
build
(int k,
int l,
int r)
int mid=l+r>>1;
build
(k<<
1,l,mid)
;build
(k<<1|
1,mid+
1,r)
;pushup
(k);
}int
query_m
(int k,
int l,
int r)
int mid=tr[k]
.l+tr[k]
.r>>1;
if(mid>=r)
else
if(midreturn
max(
query_m
(k<<
1,l,mid)
,query_m
(k<<1|
1,mid+
1,r));
}int
query_mi
(int k,
int l,
int r)
int mid=tr[k]
.l+tr[k]
.r>>1;
if(mid>=r)
else
if(midreturn
min(
query_mi
(k<<
1,l,mid)
,query_mi
(k<<1|
1,mid+
1,r));
}int
main()
build(1
,1,n);
for(
int i=
1;i+k-
1<=n;i++
)else
}for
(int i=
1;i+k-
1<=n;i++
)else
}}
單調佇列:
#include.h>
using namespace std;
//單調佇列
const
int maxn=
1e6+5;
int q[maxn]
,a[maxn]
;int n,k;
void
solv()
cout
0,tail=-1
;for
(int i=
0;iintmain()
單調佇列寫這題的空間複雜度是o(1)的,時間複雜度是o(n)的,基本上算是這題的最優解。呢麼單調佇列是如和實現的呢:單調佇列一般用於解決區間最值問題,在解決這類問題中,單調佇列中,儲存的是下標,單調佇列的頭代表最值元素,呢麼這一題的寫法就很明顯了,先判斷頭元素在不在合法區間,如果在就不管,不在就刪去頭元素即可,之後就是維護頭元素操作,詳細看**
AcWing 滑動視窗 單調佇列
時 空限制 1s 64mb 給定乙個大小為n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值最大值 1 3 1 3 5 3 6 7 13...
Acwing 154 滑動視窗 單調佇列
這題和poj2823是一樣的 解析 暴力,直接對於每k個都遍歷一遍,很顯然複雜度o nk 的話行不通。對於這類問題,有乙個比較一致的思路,就是有些數字是無用的,或者用了幾次後就要被扔掉的,後續根本就排不上用場。比如有ai,aj,ax,ax ai aj,找ax左邊第乙個比它小的數,很明顯,ai壓根不需...
單調佇列 滑動視窗
nkoj 2152 description 給你乙個長度為n n 10 6 的陣列,乙個長為k的滑動的窗體從最左移至最右端,你只能見到視窗的k個數,每次窗體向右移動一位,找出窗體所包含的數字的最大和最小值,如下表所示 k的值為3 視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 ...