单调队列总结
来源:互联网 发布:地狱无门 知乎 编辑:程序博客网 时间:2024/05/21 17:29
poj 2823 N个数,每个区间从左到右选取K个数,求每个区间中的最小值,最大值
void GetMin(){ //保持队列严格单调递增 int i , j ; int head = 0 , tail = -1 ; for(i = 1 ; i <= n ; i++){ while(head <= tail && a[que[tail]] >= a[i]) tail-- ; que[++tail] = i ; while(que[tail] - que[head] + 1 > k) head++ ; if(i == k) printf("%d" , a[que[head]]) ; else if(i > k) printf(" %d" ,a[que[head]]) ; } puts("") ;}void GetMax(){ //保持队列严格单调递减 int i , j ; int head = 0 , tail = -1 ; for(i = 1 ; i <= n ; i++){ while(head <= tail && a[que[tail]] <= a[i]) tail-- ; que[++tail] = i ; while(que[tail] - que[head] +1 > k) head++ ; if(i == k) printf("%d" , a[que[head]]) ; else if(i > k) printf(" %d" ,a[que[head]]) ; } puts("") ;}
HDU 3415 长度为N的环状序列,求长度<=K的的连续子序列的和,使得和最大
sum[i] = a[1] + a[2] + .....+ s[i] .
a[i] = sum[i] - sum[i-1] ;
a[i] + a[i-1] = sum[i] - sum[i-2] ;
.......
a[i] + a[i-1] + .....+ s[i-k+1] = sum[i] - sum[i-k] ;
如果序列以i 结束, 则和为 sum[i] - min{ j | sum[j] } (i-k <= j <= i-1) 。
void Ans(){ int i , j , head = 0 , tail = -1 , ans = -(1<<30) , L , R ; sum[0] = 0 ; for(i = 1 ; i <= n ; i++) sum[i] = sum[i-1] + a[i] ; for(i = n+1 ; i < n+k ; i++) sum[i] = sum[i-1] + a[i-n] ; int m = n + k - 1 ; for(int i = 1 ; i <= m ; i++){ while(head <= tail && sum[que[tail]] >= sum[i-1]) tail-- ; //单调递增 que[++tail] = i-1 ; while(que[head] < i-k) head++ ; if(ans < sum[i] - sum[que[head]]){ ans = sum[i] - sum[que[head]] ; L = que[head] + 1 ; R = i ; } } if(L > n) L -= n ; if(R > n) R -= n ; printf("%d %d %d\n" , ans , L , R) ;}
HDU 3474 长度为n的项链,珠子为C,J。从某处断开,从断开处往左数或者往右数,到每个点的C个数>=J个数,求断开点的总数
C = 1 , J = -1 ,维护前缀和。
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
[1->8 ] 区间min{sum} >= sum[0] 满足
[2->8->1] 区间min{sum} >= sum[1] 满足
[3->8->2] 区间min{sum} >= sum[2] 满足
.......
sum 【i-n+1 ,i】最小值 >= sum[i-n] 满足。
注意这个顺序是顺着数。 dp0[0] = [1->8] , dp0[1] = [2->8>1] 。
倒着数把串逆序。8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 dp1[0] = [8->1] , dp1[1] = [7->1->8] 。
从8 ,1 处断开。 顺【1->8】<=> dp1[0] ,逆【8->1】<=> dp2[8] 。
const int Max_N = 1000008 ;char str[Max_N] ;int sum[Max_N*2] , que[Max_N*2] ;int n ;void Solve(bool dp[]){ int i , j , m = n + n , head = 0 , tail = -1 ; sum[0] = 0 ; for(i = 1 ; i <= n ; i++) sum[i] = sum[i-1] + (str[i] == 'C' ? 1 : -1) ; for(i = n+1 ; i <= m ; i++) sum[i] = sum[i-1] + (str[i-n] == 'C' ? 1: -1) ; for(i = 1 ; i < n ; i++){ while(head <= tail && sum[que[tail]] >= sum[i]) tail-- ; que[++tail] = i ; } for(i = n ; i <= m ; i++){ while(head <= tail && sum[que[tail]] >= sum[i]) tail-- ; que[++tail] = i ; while(head <= tail && que[head] <= i - n) head++ ; if(sum[que[head]] >= sum[i-n]) dp[i-n] = 1 ; }}bool dp[2][Max_N] ;int main(){ int t , ans , i , T = 1 ; cin>>t ; while(t--){ scanf("%s" ,str+1) ; n = strlen(str+1) ; memset(dp , 0 , sizeof(dp)) ; Solve(dp[0]) ; std::reverse(str+1 , str+1+n) ; Solve(dp[1]) ; ans = 0 ; for(i = 0 ; i < n ; i++) ans += (dp[0][i] | dp[1][n-i]) ; printf("Case %d: %d\n" ,T++ , ans) ; } return 0 ;}
0 0
- 单调队列 单调栈总结
- 单调队列,单调栈总结
- 单调队列总结
- 单调队列与单调栈总结
- 【动态规划10】单调队列总结
- 单调栈 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- Android px与dip, px与sp之间转化工具类
- C++ 继承 必须注意的地方
- jps命令使用
- PKI 介 绍
- 唐高祖李渊
- 单调队列总结
- Leetcode-Remove Nth Node From End of List
- 8-2 实现Time类中的运算符重载
- 搜狐焦点张冰:从圈客到圈脑 用应战去赢战
- 虚拟系统设置局域网内网互通
- linux--webmin的安装
- STARTUP.A51详解 .
- Set Matrix Zeroes
- 权限模型