http://acm.hdu.edu.cn/showproblem.php?pid=6058
题意:求区间第K大然后乘以它本身的总和
思路:枚举X,维护一个链表,这个链表是记录比它小的一些,比他大的有多少个的一个链表
因为在这个链表中隔K个的值,然后取第K大就一定是X
然后维护这个链表呢,就是指已经枚举过的X就不要出现在这个链表里面了,因为如果它的值比这个X要小的话,肯定是不会影响这个第K大的
然后不可能出现比它大的情况,因为我们枚举X是从小到大枚举的,所以这个问题就可以化解
1 #include <stdio.h> 2 #include <string.h> 3 #define maxn 500005 4 5 struct Node { 6 int pre, next; 7 int val; 8 }node[maxn]; 9 10 int next[maxn]; 11 int pre[maxn]; 12 13 int main() 14 { 15 int t, a; 16 int m, k; 17 scanf("%d", &t); 18 while (t--) 19 { 20 scanf("%d%d", &m, &k); 21 for (int i = 1; i <= m; i++) { 22 scanf("%d", &a); 23 node[i].pre = i - 1; 24 node[i].next = i + 1; 25 node[a].val = i; 26 } 27 long long ans = 0; 28 for (int i = 1; i <= m - k+1; i++) 29 { 30 int pos = node[i].val; 31 int pr = 0; 32 int ne = 0; 33 for (int j = pos; j&&pr <= k + 1; j = node[j].pre) pre[++pr] = j; //找到前面比它小的 34 for (int j = pos; j&&ne <= k + 1; j = node[j].next) next[++ne] = j; //找到后门比它大的 35 pre[++pr] = 0; 36 next[++ne] = m + 1; 37 for (int j = 1; j < pr; j++) 38 { 39 if (k - j + 1 < ne && k - j + 1 >= 1) 40 { 41 ans += (long long)(next[k + 1 - j + 1] - next[k + 1 - j])*(pre[j] - pre[j + 1])*i; //i一定为这个区间的第K大 42 } 43 } 44 node[node[pos].pre].next = node[pos].next; //链表的维护 45 node[node[pos].next].pre = node[pos].pre; 46 node[pos].pre = node[pos].next = 0; 47 } 48 printf("%lld\n", ans); 49 } 50 return 0; 51 }
时间: 2024-10-12 23:57:21