Kanade's sum
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
题解:
我们只要求出对于一个数x左边最近的k个比他大的和右边最近k个比他大的,扫一下就可以知道有几个区间的k大值是x.
我们考虑从大到小插入空位,每次维护一个链表,链表里只有>=x的数,那么往左往右找只要暴力跳k次,删除也是O(1)的。
时间复杂度:O(nk)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; typedef unsigned long long ULL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 1e6+10, M = 1e3+20,inf = 2e9,mod = 1e9 + 7; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,k,a[N],pos[N],lef[N],righ[N],L[N],R[N]; set<int > G; set<int >:: iterator it,itt; void insers(int x,int y) { int tmp = L[x]; L[y] = tmp; R[y] = x; R[tmp] = y; L[x] = y; } int main() { int T; T = read(); while(T--) { G.clear(); n = read(); k = read(); for(int i = 1; i <= n; ++i) { a[i] = read(); pos[a[i]] = i; } if(k == 0) { puts("0"); continue; } G.insert(0); G.insert(n+1); L[0] = -1; R[0] = n+1; L[n+1] = 0; R[n+1] = -1; for(int i = n; i > n - k + 1; --i) { it = (G.lower_bound(pos[i])); insers(*it,pos[i]); G.insert(pos[i]); } LL ans = 0; for(int i = n-k+1; i >= 1; --i) { it = (G.lower_bound(pos[i])); int po = *it; for(int j = 0; j <= k; ++j) lef[j] = -1; lef[0] = pos[i]; for(int j = 1,h = L[po]; j <= k && h != -1; ++j, h = L[h]) { lef[j] = h; } po = *it; righ[0] = pos[i]; for(int j = 1,h = po; j <= k && h != -1; ++j, h = R[h]) { righ[j] = h; if(lef[k-j+1] != -1) ans += 1LL*i*(lef[k-j] - lef[k - j + 1]) * (righ[j] - righ[j-1]); } insers(*it,pos[i]); G.insert(pos[i]); } printf("%lld ",ans); } return 0; }