滑窗求最大值 (单调栈)

原题 : Problem A. Ascending Rating

题意:

给n个数的数组,求a和b的和
a:每个m长度的子数列的最大值^子数列第一个位置下标
b:每个m长度的子数列的上升数^子数列第一个位置下标
上升数:从第一个开始,遇到大于前一个上升数的所有数(5 2 1 4 6)->(5 6)

解析:

在比赛的时候,我想到了单调栈,但是我是从前往后进栈,这样做的坏处还是很明显的

在删去栈底的较小元素的时候,可能有下面这种情况,5 1 1 1 1 1 6,因为这道题题意的原因,5 6会变成1 1 1 1 1 6,不单单是栈底下扩的问题,对于单调递减的数组n*n的时间我也是…

从后往前维护单调栈,栈底就是最大值,栈size就是上升数

代码:


D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}

int arr[10000009];
int q[20000009];int top,bot;


int main(){
    int t=read();
    while(t--){
        int n,len,k,p,qq,r,mo;scanf("%d%d%d%d%d%d%d",&n,&len,&k,&p,&qq,&r,&mo);
        for(int i=1;i<=k;i++)scanf("%d",&arr[i]);
        for(int i=k+1;i<=n;i++)arr[i]=((D)p*arr[i-1]+(D)qq*i+r)%mo;

        D sa=0,sb=0;
        top=0;bot=1;
        for(int i=n;i>=1;i--){
            while(top>=bot&&arr[i]>=arr[q[top]])top--;
            q[++top]=i;
            int en=i+len-1;
            if(i<=n-len+1){
            while(q[bot]>en)bot++;sa+=(D)i^arr[q[bot]],sb+=(D)i^(top-bot+1);}
            //printf("add %d^%d %d^%d\n",i,arr[q[top]],i,(top-bot+1));
        }
        printf("%lld %lld\n",sa,sb);
    }
}

这题我后来卡了很久,就因为(D)p*arr[i-1]+(D)qq*i+r,以前我以为一个算式里面有一个long long就不用担心爆int,有一个double就不会爆精度,不过今天我只加了加号前面的部分的强制转换,发现居然WA了…

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/81291170