枚举1到n,当i是第k大时,区间左端点到右端点 比i大的数必须=k-1个
将a[1..n]放链表里,枚举完i,则将i删去,则链表中所有元素都>当前枚举的数,O(k)即可统计出区间个数
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int N = 5e5+5;
int a[N];
int idx[N];
list<int>::iterator Ref[N];
list<int>ls;
ll slove(int n,int k){
list<int>::iterator itL,itR;
int cntL,cntR;
ll ans=0;
for(int i=1;i<=n;++i){
itL=itR=Ref[i];
cntL=0,cntR=0;//itL-Ref[i]间多少个数比i大 ,itR-Ref[i]间...
for(int x=0;x<=k-1;++x){
while(cntR<k-1-x&&itR!=Ref[n+1]){
++itR;
++cntR;
}
if(cntR>k-1-x||itR==Ref[n+1]){
--itR;
--cntR;
}
if(cntR+cntL==k-1){
int CountL,CountR=CountL=1;
auto tmp=itL;
--tmp;
CountL=idx[*itL]-idx[*tmp];
tmp=itR;
++tmp;
CountR=idx[*tmp]-idx[*itR];
ans+=(ll)CountL*CountR*i;
}
--itL;
if(itL==Ref[0]){
break;
}
++cntL;
}
ls.erase(Ref[i]);
}
return ans;
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d%d",&n,&k);
ls.clear();
ls.push_back(0);
idx[0]=0;
Ref[0]=ls.begin();
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
ls.push_back(a[i]);
Ref[a[i]]=--ls.end();
idx[a[i]]=i;
}
ls.push_back(n+1);
idx[n+1]=n+1;
Ref[n+1]=--ls.end();
printf("%lld\n",slove(n,k));
}
return 0;
}