HDU 6319 Problem A. Ascending Rating(单调队列)

要求一个区间内的最大值和每次数过去最大值更新的次数,然后求每次的这个值异或 i 的总和。

这个序列一共有n个数,前k个直接给出来,从k+1到n个数用公式计算出来。

因为要最大值,所以就要用到单调队列,然后从后往前扫一遍然后每次维护递减的单调队列。

先把从n-m+1以后开始的数放进单调队列,这时候先不操作,然后剩下的数就是要异或相加的数,然后每次的队首元素就是这个区间内的最大值,这个队列里的元素个数,其实就是更新到最大值的逆过程,也就是最大值需要更新的次数。

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 10000100;
const int maxm = 1000005;
using namespace std;

int T, tol;
int n, m;
ll a[maxn];
int que[maxn];

void init() {
    memset(a, 0, sizeof a);
}

int main() {
    scanf("%d", &T);
    while(T--) {
        int k;
        int p, q, r, mod;
        scanf("%d%d%d%d%d%d%d", &n, &m, &k, &p, &q, &r, &mod);
        for(int i=1; i<=k; i++)    scanf("%lld", &a[i]);
        for(int i=k+1; i<=n; i++)    a[i] = (1ll*p*a[i-1] + 1ll*q*i + r) % mod;
        int head, tail;
        head = tail = 0;
        for(int i=n; i>n-m+1; i--) {
            while(head != tail && a[i] >= a[que[tail-1]])    tail--;
            que[tail++] = i;
        }
        /*
        for(int j=head; j<tail; j++)    printf("%d %d %lld
", i, que[j], a[que[j]]);
        printf("
");
        */
        ll ans1 = 0;
        ll ans2 = 0;
        for(int i=n-m+1; i>=1; i--) {
            while(head != tail && a[i] >= a[que[tail-1]])    tail--;
            que[tail++] = i;
            while(i + m - 1 < que[head])    head++;
            /*
            for(int j=head; j<tail; j++)    printf("%d %d %lld
", i, que[j], a[que[j]]);
            printf("
");
            */
            ans1 += (a[que[head]] ^ i);
            ans2 += ((tail - head) ^ i);
        }
        printf("%lld %lld
", ans1, ans2);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/9395239.html