Problem A. Ascending Rating
题意:在一个数列a中任选一个长度为m的区间;设maxrating和count初始值均为0,然后从该区间的左边第一个位置开始遍历该区间,没遇到一个大于maxrating的数x,就将maxrating改为x,同时count++;遍历完该区间后就得到了该区间的maxrating值和count值;
求A,B的值;表示异或运算;
思路:首先maxrating怎么找?遍历一遍直接维护区间最大值;维护一个单调递增的栈,这样maxrating就出来了,哎~维护的栈中的数的个数是不是就是count??哇塞,好像!!!可惜并不是~~~因为第一个是从头开始的,这样只是找出第一个区间的count了,第二个区间不还是要从头开始找。。。count其实就是区间中单调递增的长度,倒过来不就是单调递减的长度???没错是这样;
现在到这维护一个长度为m的单调减栈,栈尾就是maxrating,栈内数的个数就是count;
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e7+10;
long long a[maxn];
long long sta[maxn];
int main(){
int T;
scanf("%d", &T);
while(T--){
long long 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("%d", &a[i]);
for(int i=k+1; i<=n; i++)
a[i]=(int)((long long)(p*a[i-1]+q*i+r)%mod);
long long A, B;
A=B=0;
int top=0, ft=0;
for(int i=n; i>0; i--){
while(top>ft&&a[i]>=a[sta[top]]) top--;
sta[++top]=i;
while(sta[ft+1]-sta[top]>=m) ft++;
if(i<=n-m+1){
A+=a[sta[ft+1]]^(long long)i;
B+=(long long)(top-ft)^(long long)i;
}
}
printf("%lld %lld\n", A, B);
}
return 0;
}