hdu6319 Ascending Rating(滑动窗口)

滑动窗口的作用:

1.求一个数组arr[n]中 每个固定长度为m的连续区间的最大值/最小值,复杂度O(n)

2.求一列数  a1 a2 .... an 从左到右,最大值变化的次数,比如 4 1 5 10 7 9 ,变化次数为 3 (4-->5--->10)

用双端队列就可以完成,把数组变量放全局位置,不然可能会报 RuntimeError 栈溢出。

没接触过这个算法,不会做,哎,还是好好加油吧。

//滑动窗口 
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1e7+10;
int t;
ll arr[maxn];
ll dq[maxn];
ll n,m,k,p,q,r,mod;
ll front,back;
ll A,B;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mod);
        for(int i=1;i<=k;i++)
        {
            scanf("%lld",&arr[i]);
        }
        for(int i=k+1;i<=n;i++)
        {
            arr[i] = (p*arr[i-1] + q*i + r)%mod;
        }
        //滑口大小m 
        A = B = 0;
        front = back = 0; 
        ll j = n-m+1;
        for(ll i=n;i>j;i--)
        {
            while(back>front && arr[dq[back-1]]<=arr[i]) back--;
            dq[back++] = i;
        }
        for(ll i=j;i>=1;i--)
        {
            while(back>front && arr[dq[back-1]]<=arr[i]) back--;
            dq[back++] = i;
            //到了 
            A = A + (arr[dq[front]] ^ (i));
            B = B + ((back-front) ^ (i));
            if(dq[front]>=i+m-1)
            {
                front++;
            }
        }
        printf("%lld %lld\n",A,B); 
    }
    return 0;
}//3853MS C++

猜你喜欢

转载自blog.csdn.net/zark721/article/details/81319892