Problem A. Ascending Rating
题意:
给定一个序列a[1..n],对于所有长度为m的连续子区间,求出区间的最大值以及从左往右扫描该区间时a的最大值的变化次数。
1≤m≤n≤107。 Shortest judge solution: 534 bytes
题解:
官方题解:按照r从m到n的顺序很难解决这个问题。考虑按照r从n到m的顺序倒着求出每个区间的答案。按照滑窗最大值的经典方法维护a的单调队列,那么队列中的元素个数就是最大值的变化次数。时间复杂度O(n)。
最大值好算,就是变化次数要想到从后往前推。
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi first
#define se second
typedef long long ll;
const int N = 10000005;
#define pii pair<int, int>
int a[N], n, m, k, p, q, r, mod;
deque< pii > DQ;
int main()
{
int T; scanf("%d", &T);
while(T--)
{
DQ.clear();
scanf("%d%d%d%d%d%d%d", &n, &m, &k, &p, &q, &r, &mod);
rep(i,1,k) scanf("%d", &a[i]);
rep(i,k+1,n) a[i] = (1LL*p*a[i-1] + 1LL*q*i+r) %mod;
ll ans1=0, ans2=0;
per(i,n,1)
{
if(DQ.empty()) DQ.push_front(MP(a[i],i));
else {
while(!DQ.empty() && DQ.front().fi<=a[i]) DQ.pop_front();
DQ.push_front(MP(a[i],i));
}
if(i+m-1 < DQ.back().se) DQ.pop_back();
if(i <= n-m+1)
ans1 += DQ.back().fi^i, ans2 += DQ.size()^i;
}
printf("%lld %lld\n", ans1, ans2);
}
return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/9410373.html
时间: 2024-10-08 22:17:50