HDU - 6319 Ascending Rating【单调队列】

ai=(p×ai1+q×i+r)modMODai=(p×ai1+q×i+r)modM

题目链接:https://vjudge.net/problem/HDU-6319ai=(p×ai1+q×i+r)modMOD

 

题意:给你n,m,k,p,q,r,MOD,七个数,n为长度为n的数组,其中前k个数已经给出,后面的按照公式补足。

问每长度为m的区间中最大值的位置和从左到右最大值更新了多少次

答案按输出公式进行异或

思路:一开始想到的单调区间,但是是从左到右依次遍历i,然后再从第i个往前搜索m个数,过于复杂,导致做不出

应当是从右往左依次遍历,这样一次即可,单调队列中按从大到小排列,如果a[i]一直比队列末尾的数大,末尾数就一直出队

否则a[i]入队,此时队列中头元素就是区间m中最大值,队列中有多少个就是区间m中最大值更新次数

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include <sstream>
#include<vector>
#include<cmath>    
#include<stack>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define LD long double
#define LL long long
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define inf 1<<30
#define  ull unsigned long long
const int Mod = 998244353;
const int maxn = 1e7 + 9;
int read()
{
    int x = 0, f = 1; char ch = getchar();
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
int a[maxn];
int Q[maxn];
int n, m, q, p, k, r, mod, t;
int head, tail;
LL ans1, ans2;
int main()
{
    t = read();
    while (t--) {
        n = read();
        m = read();
        k = read();
        p = read();
        q = read();
        r = read();
        mod = read();
        for (int i = 1; i <= k; i++) {//读入前k个数
            a[i] = read();
        }
        for (int i = k + 1; i <= n; i++) {//按照公式补足数组
            a[i] = (1ll * p * a[i - 1] + 1ll * q * i + r) % mod;
        }
        head = 1; tail = 0;//初始化
        ans1 = ans2 = 0;
        for (int i = n; i > 0; i--) {//从右往左遍历
            while (tail >= head && a[Q[tail]] <= a[i])tail--;//队尾元素比a[i]小就出队
            Q[++tail] = i;//a[i]入队
            if (i + m - 1 <= n) {//形成了一个大小为m的区间
                while (Q[head] >= i + m)head++;//队首元素已经不在当前m区间范围,出队
                ans1 += i ^ a[Q[head]];//记录答案
                ans2 += i ^ (tail - head + 1);
            }
        }
        cout << ans1 << " " << ans2 << endl;
    }
}

 

posted @ 2021-03-22 19:47  夜灯长明  阅读(33)  评论(0编辑  收藏  举报