[LG1886]滑動窗口 單調隊列
阿新 • • 發佈:2018-10-13
別人 true inline span tps 一份 space close 什麽
~~~題面~~~
題解:
觀察數據範圍,這應該是一個復雜度O(n)的題。以最大值為例,考慮單調隊列,維護一個單調遞減的隊列。從前向後掃,每次答案取隊首,如果後面進入的比前面大,那麽就彈出前面的數,因為是從前向後掃,所以後面進入的如果比前面的大,那麽一定更優,因為要淘汰肯定先淘汰前面的。如果隊首已經不在當前窗口內了,那麽就彈出,直到合法為止。
維護單調隊列時的一個重要原則就是把別人“擠掉”的元素一定要比被擠掉的元素更優,否則可能找不到合法情況or漏掉最優解。註意這一點就很好理解了。
最小值用求最大值相反的操作即可
不知道為什麽我以前寫代碼寫那麽醜,,,,重新寫一份好了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 1001000 5 6 int n, k, head, tail; 7 int s[AC]; 8 struct node{ 9 int x, id; 10 }q[AC]; 11 12 inline int read() 13 { 14 int x = 0;char c = getchar(); bool z = false; 15 whileView Code(c > ‘9‘ || c < ‘0‘) 16 { 17 if(c == ‘-‘) z = true; 18 c = getchar(); 19 } 20 while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); 21 if(!z) return x; 22 else return -x; 23 } 24 25 void pre() 26 { 27 n = read(), k = read();28 for(R i = 1; i <= n; i ++) s[i] = read(); 29 } 30 31 void work1() 32 { 33 head = 1, tail = 0; 34 for(R i = 1; i <= n; i ++) 35 { 36 while(head <= tail && q[head].id <= i - k) ++ head; 37 while(s[i] < q[tail].x && head <= tail) -- tail;//可以刪完,反正後面要塞進來 38 q[++tail] = (node){s[i], i}; 39 if(i >= k) printf("%d ", q[head].x); 40 } 41 printf("\n"); 42 } 43 44 void work2() 45 { 46 head = 1, tail = 0; 47 for(R i = 1; i <= n; i ++) 48 { 49 while(head <= tail && q[head].id <= i - k) ++ head;//,,,前面也可以刪完 50 while(s[i] > q[tail].x && head <= tail) -- tail;//可以刪完,反正後面要塞進來 51 q[++tail] = (node){s[i], i}; 52 if(i >= k) printf("%d ", q[head].x); 53 } 54 printf("\n"); 55 } 56 57 int main() 58 { 59 freopen("in.in", "r", stdin); 60 pre(); 61 work1(); 62 work2(); 63 fclose(stdin); 64 return 0; 65 }
當然如果你喜歡簡短的代碼,且不在意常數問題,你也可以這麽寫:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 1001000 5 6 int n, k, head, tail; 7 int s[AC]; 8 struct node{ int x, id;} q[AC]; 9 10 void cal(int t) 11 { 12 head = 1, tail = 0; 13 for(R i = 1; i <= n; i ++) 14 { 15 while(head <= tail && q[head].id <= i - k) ++ head; 16 while(s[i] < q[tail].x && head <= tail) -- tail;//可以刪完,反正後面要塞進來 17 q[++tail] = (node){s[i], i}; 18 if(i >= k) printf("%d ", q[head].x * t); 19 }printf("\n"); 20 } 21 22 int main() 23 { 24 scanf("%d%d", &n, &k); 25 for(R i = 1; i <= n; i ++) scanf("%d", &s[i]); 26 cal(1); 27 for(R i = 1; i <= n; i ++) s[i] = -s[i]; 28 cal(-1); 29 return 0; 30 }View Code
[LG1886]滑動窗口 單調隊列