/*
计算每个数的贡献,
找到左边k-1个大于 pi的,右边 大于pi 的, 所有有贡献的区间都在这个范围内。
用链表维护位置,结束后删除pi, 从小到大 枚举,可以保证链表中的数 >=pi;
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mod =1e9+7;
const int Size = 510000;
int pre[Size],nxt[Size],pos[Size];
inline void read(int &x)
{
x=0;char p=getchar();
while(!(p<='9'&&p>='0')) p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int main()
{
int t,n,k;
read(t);
while(t--)
{
int p=0,x;
read(n);read(k);
for(int i=1;i<=n;i++)
{
read(x);
pos[x]=i;
nxt[p]=x;
pre[x]=p;
p=x;
}
nxt[x]=n+1;pos[n+1]=n+1;
ll ans=0;
for(int i=1;i<=n;i++)
{
p=i;
int cnt=1,p1=i;
ll sum=0;
while(cnt<k&&pre[p]) p=pre[p],cnt++;
while(cnt<k&&nxt[p1]!=n+1) p1=nxt[p1],cnt++;
if(cnt<k) continue;
for(;p!=nxt[i];p=nxt[p])
{
int l1=(pos[p]-pos[pre[p]]);
int r1=(pos[nxt[p1]]-pos[p1]);
sum +=l1*r1;
p1=nxt[p1];
if(p1==n+1) break;
}
pre[nxt[i]]=pre[i];
nxt[pre[i]]=nxt[i];
ans +=(ll)sum*i;
}
printf("%lld\n",ans);
}
return 0;
}
hdu 6058 Kanade's sum
最新推荐文章于 2018-03-31 14:54:00 发布