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

博客介绍了如何使用单调队列解决HDU在线评测系统中的一道题目,题号为6319,题目要求在给定的选手评级序列中,对于每个指定长度的子序列,找到子序列的最大评级及更新最大值的次数。输入包括选手数量、子序列长度及其他参数,评级序列部分元素可通过给定公式计算。博主给出了利用单调队列求解的思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem A. Ascending Rating

Before the start of contest, there are nn ICPC contestants waiting in a long queue. They are labeled by 11 to nn from left to right. It can be easily found that the ii-th contestant's QodeForces rating is aiai. 
Little Q, the coach of Quailty Normal University, is bored to just watch them waiting in the queue. He starts to compare the rating of the contestants. He will pick a continous interval with length mm, say [l,l+m−1][l,l+m−1], and then inspect each contestant from left to right. Initially, he will write down two numbers maxrating=−1maxrating=−1 and count=0count=0. Everytime he meets a contestant kk with strictly higher rating than maxratingmaxrating, he will change maxratingmaxrating to akak and countcount to count+1count+1. 
Little T is also a coach waiting for the contest. He knows Little Q is not good at counting, so he is wondering what are the correct final value of maxratingmaxrating and countcount. Please write a program to figure out the answer. 

Input

The first line of the input contains an integer T(1≤T≤2000)T(1≤T≤2000), denoting the number of test cases. 
In each test case, there are 77 integers n,m,k,p,q,r,MOD(1≤m,k≤n≤107,5≤p,q,r,MOD≤109)n,m,k,p,q,r,MOD(1≤m,k≤n≤107,5≤p,q,r,MOD≤109) in the first line, denoting the number of contestants, the length of interval, and the parameters k,p,q,r,MODk,p,q,r,MOD. 
In the next line, there are kk integers a1,a2,...,ak(0≤ai≤109)a1,a2,...,ak(0≤ai≤109), denoting the rating of the first kk contestants. 
To reduce the large input, we will use the following generator. The numbers p,q,rp,q,rand MODMOD are given initially. The values ai(k<i≤n)ai(k<i≤n) are then produced as follows : 

ai=(p×ai−1+q×i+r)modMODai=(p×ai−1+q×i+r)modMOD


It is guaranteed that ∑n≤7×107∑n≤7×107 and ∑k≤2×106∑k≤2×106. 

Output

Since the output file may be very large, let's denote maxratingimaxratingi and counticounti as the result of interval [i,i+m−1][i,i+m−1]. 
For each test case, you need to print a single line containing two integers AA and BB, where : 

AB==∑i=1n−m+1(maxratingi⊕i)∑i=1n−m+1(counti⊕i)A=∑i=1n−m+1(maxratingi⊕i)B=∑i=1n−m+1(counti⊕i)


Note that ``⊕⊕'' denotes binary XOR operation. 

Sample Input

1
10 6 10 5 5 5 5
3 2 2 1 5 7 6 8 2 9

Sample Output

46 11

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6319

题目大意:在长度为n的数组中,对于每个长度为 m 的连续子区间,求出子区间 的最大值以及从左往右扫描该区间时区间最大值的更新次数。

输入描述:n m k p q r  mod ,给出长度为k的数组,[ k+1,n ]区间的部分 按照公式: a[i]=(a[i-1]*p+q*i+r)%mod 计算

思路:单调队列,维护长度为m的滑动窗口的最大值,还要维护更新的次数,从后往前遍历,维护队列的单调性,此时队列的长度就是更新的次数

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
const int N=10000005;
ll a[N];
int qu[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,m,k,p,q,r,mod;
        scanf("%lld%lld%lld%lld%lld%lld%lld",&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]=((a[i-1]*p)%mod+(q*i)%mod+r)%mod;
        ll head=1,tail=0;
        ll ans1=0,ans2=0;
        for(ll i=n;i>=n-m+1;i--)
        {
            while(a[i]>=a[qu[tail]]&&head<=tail) --tail;
            qu[++tail]=i;
            if(i==n-m+1)
            {
                ans1+=a[qu[head]]^i;
                ans2+=(tail-head+1)^i;
            }
        }
        for(ll i=n-m;i>=1;i--)
        {
            while(qu[head]-i+1>m&&head<=tail)
            {
                head++;
            }
            while(a[i]>=a[qu[tail]]&&head<=tail) --tail;
            qu[++tail]=i;
            //printf("%d %lld %lld\n",i,a[qu[head]],(ll)tail-head+1);
            ans1+=a[qu[head]]^i;
            ans2+=(tail-head+1)^i;
        }
        printf("%lld %lld\n",ans1,ans2);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值