hdu3415单调队列
生活随笔
收集整理的這篇文章主要介紹了
hdu3415单调队列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你一個數字組成的環,要求在里面找到一個最大的子序列,使得和最大,要求:
(1)子序列長度不能超過k
(2)如果子序列和相同要起點最小的
(3)如果起點相同要長度最小的
思路:
? ? ? 首先環我們可以把序列放大一倍,然后Ans = maxx(sum[j] - sum[i]); ?其中j>i,j-i>=k,sum[i]是前綴和,對于每一個j我們只要找到前面最小的那個sum[i]就行了,這樣就變成了一個比較裸的一個單調隊列的題目,求最小我們的隊列可以使遞增的,每次從隊尾進,把比當前大的出隊(不是大于等于,是大的,這樣保證同樣和的時候前綴最小),隊頭的話只要把距離當前值距離大于k的出隊就行了,還有就是記住一點,每次都是先詢問在進隊,那么在詢問之前一定要判斷下隊頭的id是否過期,也就是隊頭是否要出先隊列,這個地方大一了wa了一發。?
#include<stdio.h>
#include<string.h>
#define N 200000 + 10
typedef struct
{
? ?int id ,num;
}NODE;
NODE Q[N];
int num[N];
int tou ,wei ,k;
void insert(int id ,int num)
{
? ?for(int i = wei ;i > tou ;i --)
? ?if(Q[i].num > num) wei --;
? ?else break;
? ?Q[++wei].id = id;
? ?Q[wei].num = num;
? ?for(int i = tou + 1 ;i <= wei ;i ++)
? ?if(id - Q[i].id > k) ?tou ++;
? ?else break;
}
int main ()
{
? ?int t ,n ,j ,i;
? ?int Ansa ,Ansb ,Ansc;
? ?scanf("%d" ,&t);
? ?while(t--)
? ?{
? ? ? scanf("%d %d" ,&n ,&k);
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%d" ,&num[i]);
? ? ? ? ?num[i+n] = num[i];
? ? ? }
? ? ? Ansc = - 1000000000;
? ? ? tou = wei = 0;
? ? ? int sum = 0;
? ? ? Q[++wei].num = 0;
? ? ? Q[wei].id = 0;
? ? ? num[0] = 0;
? ? ? for(i = 1 ;i <= n + n ;i ++)
? ? ? {
? ? ? ? ?sum += num[i];?
? ? ? ? ?while(i - Q[tou+1].id > k)
? ? ? ? ?tou ++; ?
? ? ? ? ?int now = sum - Q[tou+1].num;
? ? ? ? ?if(now > Ansc)
? ? ? ? ?Ansc = now ,Ansa = Q[tou+1].id + 1,Ansb = i; ??
? ? ? ? ?insert(i ,sum);
? ? ? }
? ? ? if(Ansb > n) Ansb -= n;
? ? ? printf("%d %d %d\n" ,Ansc ,Ansa ,Ansb);
? ?}
? ?return 0;
}
? ? ??
? ? ??
? ? ??
? ?
? ?
? ?
? ?
? ? ??
? ?
? ? ? 給你一個數字組成的環,要求在里面找到一個最大的子序列,使得和最大,要求:
(1)子序列長度不能超過k
(2)如果子序列和相同要起點最小的
(3)如果起點相同要長度最小的
思路:
? ? ? 首先環我們可以把序列放大一倍,然后Ans = maxx(sum[j] - sum[i]); ?其中j>i,j-i>=k,sum[i]是前綴和,對于每一個j我們只要找到前面最小的那個sum[i]就行了,這樣就變成了一個比較裸的一個單調隊列的題目,求最小我們的隊列可以使遞增的,每次從隊尾進,把比當前大的出隊(不是大于等于,是大的,這樣保證同樣和的時候前綴最小),隊頭的話只要把距離當前值距離大于k的出隊就行了,還有就是記住一點,每次都是先詢問在進隊,那么在詢問之前一定要判斷下隊頭的id是否過期,也就是隊頭是否要出先隊列,這個地方大一了wa了一發。?
#include<stdio.h>
#include<string.h>
#define N 200000 + 10
typedef struct
{
? ?int id ,num;
}NODE;
NODE Q[N];
int num[N];
int tou ,wei ,k;
void insert(int id ,int num)
{
? ?for(int i = wei ;i > tou ;i --)
? ?if(Q[i].num > num) wei --;
? ?else break;
? ?Q[++wei].id = id;
? ?Q[wei].num = num;
? ?for(int i = tou + 1 ;i <= wei ;i ++)
? ?if(id - Q[i].id > k) ?tou ++;
? ?else break;
}
int main ()
{
? ?int t ,n ,j ,i;
? ?int Ansa ,Ansb ,Ansc;
? ?scanf("%d" ,&t);
? ?while(t--)
? ?{
? ? ? scanf("%d %d" ,&n ,&k);
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%d" ,&num[i]);
? ? ? ? ?num[i+n] = num[i];
? ? ? }
? ? ? Ansc = - 1000000000;
? ? ? tou = wei = 0;
? ? ? int sum = 0;
? ? ? Q[++wei].num = 0;
? ? ? Q[wei].id = 0;
? ? ? num[0] = 0;
? ? ? for(i = 1 ;i <= n + n ;i ++)
? ? ? {
? ? ? ? ?sum += num[i];?
? ? ? ? ?while(i - Q[tou+1].id > k)
? ? ? ? ?tou ++; ?
? ? ? ? ?int now = sum - Q[tou+1].num;
? ? ? ? ?if(now > Ansc)
? ? ? ? ?Ansc = now ,Ansa = Q[tou+1].id + 1,Ansb = i; ??
? ? ? ? ?insert(i ,sum);
? ? ? }
? ? ? if(Ansb > n) Ansb -= n;
? ? ? printf("%d %d %d\n" ,Ansc ,Ansa ,Ansb);
? ?}
? ?return 0;
}
? ? ??
? ? ??
? ? ??
? ?
? ?
? ?
? ?
? ? ??
? ?
總結
以上是生活随笔為你收集整理的hdu3415单调队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu3706基础的单调队列
- 下一篇: hdu5108枚举因子求最小的m