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

Problem A. Ascending Rating

 题目链接:HDU - 6319 

题意:在一个数列a中任选一个长度为m的区间;设maxrating和count初始值均为0,然后从该区间的左边第一个位置开始遍历该区间,没遇到一个大于maxrating的数x,就将maxrating改为x,同时count++;遍历完该区间后就得到了该区间的maxrating值和count值;

求A,B的值;\bigoplus表示异或运算;

思路:首先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;
}

猜你喜欢

转载自blog.csdn.net/Sirius_han/article/details/81318266
今日推荐