首页 > 代码库 > hdu 6058

hdu 6058

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 }

 

hdu 6058