问题 A: Problem A. Ascending Rating
时间限制: 5 Sec 内存限制: 512 MB
提交: 51 解决: 14
[提交] [状态] [讨论版] [命题人:admin]
题目描述
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.
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 m,
say [l, l + m − 1], and then inspect each contestant from left to right. Initially, he will write down two
numbers maxrating = 0 and count = 0. Everytime he meets a contestant k with strictly higher rating
than maxrating, he will change maxrating to ak and count to count + 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 maxrating and count. Please write a program to figure
out the answer.
Note that “⊕” denotes binary XOR operation.
/upload/file/20180730/20180730153658_79891.pdf
样例输入
1 10 6 10 5 5 5 5 3 2 2 1 5 7 6 8 2 9
样例输出
46 11
題意:一个长度为n的序列,输入给出来k个数,剩下的n-k+ 1个数由逆推公式得出,求出所有区何[i, i+m+ 1]的最大值异或i的和和在着一个区间最大値変化次数异或i的和
双端队列:单调队列倒着跑最大値, count= 最大値変化的次数;
别人写的题意:
题目意思比较绕,反正就是一个滑块的问题,
每次滑块区间动一次要累计其count和最大值,
(count就是最长递增序列的长度,注意,是要从头往后数,不能跳)。
参数中的p,q,r,mod都是虚的,用于扩充序列而已。
对于一个序列,用单调队列维护滑块区间,
不要用STL尽量,有说不尽的毛病,能用数组就用数组,(还有数组开全局。)
单调队列的性质,它如何降低了复杂度呢?
比如初始化一个长度为k的序列,不难维护一个单调的序列,
由于我们只要最大值和最长单调长度,所以初始化的队列符合要求。
那么如果进了一个新元素呢?
如果比最小值小(咱们是倒着放的,比如9,8,7,现在进个2这样)
那么显然直接添加,如果大的话则贪心删除直至维护单调性质即可。
区间动的时候也删除了一个元素,只要这个元素不是我们区间维护的想要的答案,
就不做操作,如果是单调队列倒退,比如9,8,7,现在尾端下标离开了9的位置,则9退出队列。
倒退的那一端我们利用来判断是否对答案产生影响,前进的那一端我们
用来分析对单调队列整体的影响。
#include <bits/stdc++.h>
typedef long long ll;
const int maxn=1e7+100;
ll a[maxn];
int nod[maxn];
int n,m,k,q,r,p,mod;
int main()
{
int t;
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]+1ll*q*i+r)%mod;
}
int l = 1;
int r = 0;
ll A = 0, B = 0;
for(int i = n ;i >0 ; i--)
{
while(l<=r&&(a[nod[r]]<=a[i]))
r--;
nod[++r] = i;
if(i+m-1<=n)
{
while(nod[l]>=i+m)
l++;
A += i^a[nod[l]];
B += i^ (r-l+1);
}
}
printf("%lld %lld\n",A,B);
}
return 0;
}