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
Problem Description
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
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
Input
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]
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]
Output
For each test case,output an integer, which means the answer.
Sample Input
1
5 2
1 2 3 4 5
Sample Output
30
Source
Recommend
题目大意:给出一个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 ",ans); } return 0; }