区间第K大
对于每个数我们考虑它对答案的贡献是多少,它在哪些区间里是第k大的
这道题我们用双向链表实现
for(i = 1~n),把值为i的位置从链表里面删除

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 501000; int l[N],r[N],pos[N],le[N],ri[N]; int main() { int n,k; cin>>n>>k; for(int i = 1;i<=n;i++) { int p; cin>>p; pos[p] = i; } for(int i = 0;i<=n+1;i++) { l[i] = max(i-1,0); r[i] = min(i+1,n+1); } ll ans = 0; for(int i = 1;i<=n;i++) { int x = pos[i]; le[0] = x; for(int j = 1;j<=k;j++) { x = l[x]; le[j] = x; } x = pos[i]; ri[0] = x; for(int j = 1;j<=k;j++) { x = r[x]; ri[j] = x; } x = pos[i]; l[r[x]] = l[x]; r[l[x]] = r[x]; ll seg = 0; for(int j = 1;j<=k;j++) { seg += 1ll*(le[j-1]-le[j])*(ri[k-j+1]-ri[k-j]); } ans += seg*i; } cout<<ans<<endl; return 0; }
|