您的位置:首页 > 其它

hdu 6058 Kanade's sum(模拟链表)

2017-08-14 14:17 501 查看

Kanade's sum

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2723 Accepted Submission(s): 1132


[align=left]Problem Description[/align]
Give you an array A[1..n]of length n.

Let f(l,r,k) be the k-th largest element of A[l..r].

Specially , f(l,r,k)=0 if r−l+1<k.

Give you k , you need to calculate ∑nl=1∑nr=lf(l,r,k)

There are T test cases.

1≤T≤10

k≤min(n,80)

A[1..n] is a permutation of [1..n]

∑n≤5∗105

[align=left]Input[/align]
There is only one integer T on first line.

For each test case,there are only two integers n,k on first line,and the second line consists of n integers which means the array A[1..n]

[align=left]Output[/align]
For each test case,output an integer, which means the answer.

[align=left]Sample Input[/align]

1

5 2
1 2 3 4 5

[align=left]Sample Output[/align]

30

[align=left]Source[/align]
2017 Multi-University Training Contest - Team 3

[align=left]Recommend[/align]
liuyiding | We have carefully selected several similar problems for you: 6119 6118 6117 6116 6115

题目大意:给出一个n和一个k,求1~n的每个区间的第k大的总和是多少,区间长度小于k的话,贡献为0.

题解:一开始先维护一个满的链表,然后从小到大删除,每次算完一个数,就在链表里面删除,算x的时候,保证删除的数都比x小,都可以用来算贡献。i和pre[i]和nxt[i]的距离就是小于当前的数的数目+1。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int T,n,k;
long long ans;
int pos[1000005],a[1000005];
int pre[1000005],nxt[1000005];
long long lnum[1000],rnum[1000];

void del(int p)
{
pre[nxt[p]]=pre[p];
nxt[pre[p]]=nxt[p];
}

int main()
{
scanf("%d",&T);
for(;T>0;T--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[a[i]]=i;
}

for(int i=1;i<=n;i++)
{
pre[i]=i-1;
nxt[i]=i+1;
}
ans=0;

for(int i=1;i<=n-k+1;i++) //枚举第 k 大的数是 i 时
{
int l=0,r=0;

for(int j=pos[i];j>0 && l<=k;j=pre[j])  // 在i这个数位置的左边,比i大的k个数的位置
lnum[++l]=j-pre[j];

for(int j=pos[i];j<=n && r<=k;j=nxt[j]) // 在i这个数位置的右边,比i大的k个数的位置
rnum[++r]=nxt[j]-j;

for(int j=1;j<=l;j++)
if (k-j+1<=r && k-j+1>=1)  // 求的是一个区间内,已经满足i为第k大的情况下,能微调的位置种数(lnum[j]-lnum[j+1])*(rnum[k-j+2]-rnum[k-j+1])
ans=ans+lnum[j]*rnum[k-j+1]*i;

del(pos[i]); //删除

}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: