码迷,mamicode.com
首页 > 其他好文 > 详细

Ascending Rating

时间:2019-01-25 22:50:19      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:元素   inline   ns2   pre   show   read   过期   printf   输出   

题目传送门Ascending Rating:

给定一个序列\(a[1...n]\),对于每个长度为\(m\)的连续子区间,求出区间的最大值以及从左往右扫描该区间时最大值的变化次数。

考虑到输出可能很大,分别求出异或和即可.

一个长度为n的序列,给出序列的前k个值,剩下的\([k+1,n]\)可以由题目给出的公式推出.

把每个长度为m的区间看作滑动窗口,其实本题就是滑动窗口的升级版.

while(T--){
    ans1=ans2=0;
    n=read();m=read();k=read();
    p=read();q=read();r=read();mod=read();
//p,q,r,mod仅用于推出剩下的序列
    for(int i=1;i<=k;i++)a[i]=read();
//给出序列的前k个值
    for(int i=k+1;i<=n;i++)
        a[i]=(1LL*p*a[i-1]+1LL*q*i+r)%mod;
//由题目给出的公式推出剩下的序列
    int l=1,r=0;
    for(int i=n;i>=1;i--){//从后往前扫描
        while(l<=r&&a[Q[r]]<=a[i])r--;
//队列Q中记录的是元素的编号(1~n),而不是元素的值
//构建单调递减的队列
        Q[++r]=i;
//将这个元素入队
        if(i+m-1<=n){//小区间m全部在序列n中
            while(Q[l]>=i+m)l++;
//把"过期"的元素踢出队列
            ans1+=i^a[Q[l]];
            ans2+=i^(r-l+1);
//因为我们构建的是单调递减队列,所以队头元素是最大值.
//又因为是从后往前扫描,相当于从前往后的单调递增队列
//所以队列长度就是最大值更新的次数
        }
    }
    printf("%lld %lld",ans1,ans2);
    printf("\n");
}

Ascending Rating

标签:元素   inline   ns2   pre   show   read   过期   printf   输出   

原文地址:https://www.cnblogs.com/PPXppx/p/10321990.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!