Problem A. Ascending RatingTime Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3867 Accepted Submission(s): 1275 Problem Description Before the start of contest, there are n ICPC contestants waiting in a long queue. They are labeled by 1 to n from left to right. It can be easily found that the i -th contestant's QodeForces rating is ai . Input The first line of the input contains an integer T(1≤T≤2000) , denoting the number of test cases. ai=(p×ai−1+q×i+r)modMOD It is guaranteed that ∑n≤7×107 and ∑k≤2×106 .Output Since the output file may be very large, let's denote maxratingi and counti as the result of interval [i,i+m−1] .For each test case, you need to print a single line containing two integers A and B , where :
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 Source 2018 Multi-University Training Contest 3 Recommend chendu | We have carefully selected several similar problems for you: 6331 6330 6329 6328 6327 |
题意:给定一个长度为 n 的序列,给出前 k 个值,后面根据公式自己算 n-k 个数。现在问你
A == 每个区间长度为m的子序列最大值异或上 i 的和;
B == 最大值变化次数异或上 i 的和。
题解:从后到前遍历一遍,开一个数组模拟队列,记录最长递减子序列,在 i <= n-m+1 期间,队列的的 l(队头),r(队尾)需 要不断地更新区间。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack>
#include<list>
#include<algorithm>
using namespace std;
typedef long long ll;
const int M=70000005;
ll a[M];
ll qq[M];
int main(){
int t,n,m,k,p,q,r,mod;
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<=k;i++){
scanf("%lld",&a[i]);
}
for(int i=k+1;i<=n;i++){
a[i]=(1ll*p*a[i-1]%mod+1ll*q*i%mod+r%mod)%mod; // 注意
// a[i]=(1ll*p*a[i-1]+q*i+r)%mod; 会错
}
ll A=0,B=0;
int l=0,r=0; // l 队头指针;;r 队尾指针
for(int i=n;i>=1;i--){
while(r>l&&a[qq[r-1]]<=a[i]) r--; // 逆序求单调递减序列
qq[r++]=i;
if(i>(n-m+1)) continue; // (i 取值 在 1 - n-m+1)
while(qq[l]>(i+m-1)) l++; // 区间不断向前移动
B+=1ll*(r-l)^i; // 队尾减队头 是变化的次数
A+=1ll*a[qq[l]]^i; // 队头存放的是最大元素
}
printf("%lld %lld\n",A,B);
}
return 0;
}