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