hdu6319 Ascending Rating /// 单调队列

题目大意:

给定n m k,p q r mod,

给出序列的前k项 之后的按公式 a[i]=(p×a[i-1]+q×i+r)%mod 递推

求序列中每个长度为m的连续区间的

该区间最大值与第一位的位置异或 的总和

该区间的最长上升子序列长度与第一位的位置异或 的总和

区间最大值。。可参考另篇单调队列题解滑动最小值

从后向前维护单调队列的话

对于第i个位置为第一位的对应区间来说 

单调队列中的最大值为区间最大值

单调队列的长度就是从区间最大值到a[i]的最长下降子序列长度

(反过来即从a[i]到区间最大值的最长上升子序列长度)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e7+5;
int n,m,k,p,q,r,mod,a[N],que[N];
int main()
{
    int t; scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod);
        for(int i=1;i<=n;i++) {
            if(i>k)
            a[i]=(((LL)p*a[i-1])%mod+(LL)q*i%mod+(LL)r)%mod;
            else scanf("%d",&a[i]);
        }
        LL MAX=0, CNT=0;
        int L=0, R=0;
        for(int i=n;i>0;i--) {
            while(L<R && a[que[R-1]]<=a[i]) R--;
            que[R++]=i;

            if(i+m-1<=n) {
                while(que[L]>i+m-1 && L<R) L++;
                MAX+=(i^a[que[L]]);
                CNT+=(i^(R-L));
            }
        } 

        printf("%lld %lld
",MAX,CNT);
    }


    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/10290341.html