Make Rounddog Happy

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 608    Accepted Submission(s): 273


 

Problem Description

Rounddog always has an array a1,a2,⋯,an in his right pocket, satisfying 1≤ai≤n.

A subarray is a non-empty subsegment of the original array. Rounddog defines a good subarray as a subsegment al,al+1,⋯,ar that all elements in it are different and max(al,al+1,…,ar)−(r−l+1)≤k.

Rounddog is not happy today. As his best friend, you want to find all good subarrays of a to make him happy. In this case, please calculate the total number of good subarrays of a.

Input

The input contains several test cases, and the first line contains a single integer T (1≤T≤20), the number of test cases.

The first line of each test case contains two integers n (1≤n≤300000) and k (1≤k≤300000).

The second line contains n integers, the i-th of which is ai (1≤ai≤n).

It is guaranteed that the sum of n over all test cases never exceeds 1000000.

Output

One integer for each test case, representing the number of subarrays Rounddog likes.

Sample Input

2

5 3

2 3 2 2 5

10 4

1 5 4 3 6 2 10 8 4 5

Sample Output

7

31

 

 

题意

给出k和一个长度为n的数组a,求有多少个子区间[l,r]满足max(al,al+1,…,ar)−(r−l+1)≤k并且子区间的数互不相同

 

 

 

题解

考虑分治

我们先把线段按照最大值的pos分成左右两段

我们可以计算跨过pos的可行线段

但是注意,由于pos的位置不一定是中点,所以我们应该枚举长度较小的一段上的点,把它固定为一端端点来进行计算

怎么计算呢?

对于每一个点我们预处理出,它向左最长能延伸多远且没有相同的数,再算一下右边的

然后与k、pos和l,r进行大力分类讨论

就可以分治计算了

 

有一个小技巧:把ST表开成pair<int,int>就可以静态查找区间最大值的位置

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
    char c;int num=0,flg=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
    while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
    return num*flg;
}
#define N 300005
#define LOG 19
int n,k;
pair<int,int> f[N][LOG+3];
int tong[N],a[N],L[N],R[N],lg[N];
int query(int l,int r)
{
    int t=lg[r-l+1]-1;
    return max(f[l][t],f[r-(1<<t)+1][t]).second;
}
long long ans;
void FZ(int l,int r)
{
    if(l>r) return;
    int pos=query(l,r),i,mxlen=a[pos]-k,_l,_r;
    if(r-pos>pos-l){
        for(i=l;i<=pos;i++){
            _l=max(pos,i+mxlen-1);
            _r=min(r,R[i]);
            if(_r>=_l)
                ans+=1ll*_r-1ll*_l+1ll;
        }
    }
    else{
        for(i=r;i>=pos;i--){
            _r=min(pos,i-mxlen+1);
            _l=max(l,L[i]);
            if(_r>=_l)
                ans+=1ll*_r-1ll*_l+1ll;
        }
    }
    FZ(l,pos-1);
    FZ(pos+1,r);
}
int main()
{
    int T,i,j;
    T=gi();
    for(i=1;i<=300000;i++)
        lg[i]=lg[i>>1]+1;
    while(T--){
        memset(f,0,sizeof(f));
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        n=gi();k=gi();
        for(i=1;i<=n;i++){
            a[i]=gi();
            f[i][0]=make_pair(a[i],i);
        }
        for(j=1;j<=LOG;j++)
            for(i=1;i+(1<<j)-1<=n;i++)
                f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        memset(tong,0,sizeof(tong));L[0]=1;
        for(i=1;i<=n;i++){
            L[i]=max(L[i-1],tong[a[i]]+1);
            tong[a[i]]=i;
        }
        memset(tong,0x3f,sizeof(tong));R[n+1]=n;
        for(i=n;i>=1;i--){
            R[i]=min(R[i+1],tong[a[i]]-1);
            tong[a[i]]=i;
        }
        ans=0;
        FZ(1,n);
        printf("%lld\n",ans);
    }
}

 

 

相似的题:https://www.luogu.org/problem/CF997E