hdu6058

题意

定义 \(f(l, r, k)\) 函数为区间 \([l, r]\) 第 \(k\) 大的数,如果 \(r - l + 1 < k\),\(f = 0\) 。求 \(\sum_{l=1}^{n}\sum_{r=l}^{n}f(l, r, k)\) 。

分析

我们直接去算每个数字在多少个区间为第 \(k\) 大的数,那么一定和它前面和后面的 \(k\) 个大于它的数有关(如果有的话),现在问题就是怎么快速找出它前面和后面大于它的 \(k\) 个数。

对于 \([1, n]\) 每个数,用两个数组分别指向它所在的位置前面的值和后面的值的位置,那么从 \(1\) 到 \(n\) 计算,算完之后删掉(更改它后面的值向前的指向,更改它前面的值向后的指向),这样对于每个数向左向右最多跳 \(k\) 次。复杂度 \(O(k * n)\) 。

code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 5e5 + 10;
int n, k;
int pre[MAXN], nxt[MAXN], pos[MAXN];
int l[MAXN], r[MAXN];
void del(int x) {
pre[nxt[x]] = pre[x];
nxt[pre[x]] = nxt[x];
}
ll cal(int x) {
int c1 = 0, c2 = 0;
for(int i = x; i > 0; i = pre[i]) {
l[++c1] = i - pre[i];
if(c1 == k) break;
}
for(int i = x; i <= n; i = nxt[i]) {
r[++c2] = nxt[i] - i;
if(c2 == k) break;
}
ll res = 0;
for(int i = 1; i <= c1; i++) {
if(k - i + 1 <= c2) {
res += 1LL * l[i] * r[k - i + 1];
}
}
return res;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
pos[x] = i;
pre[i] = i - 1;
nxt[i] = i + 1;
}
pre[0] = 0; nxt[n + 1] = n + 1;
ll ans = 0;
for(int i = 1; i <= n; i++) {
ans += cal(pos[i]) * i;
del(pos[i]);
}
printf("%lld\n", ans);
}
return 0;
}

hdu6058的更多相关文章

  1. hdu6058[链表维护] 2017多校3

    用一个双向链表来查找比当前元素大的前k-1个元素和后k-1个元素 ,从小到大枚举x,算完x的贡献后将x从链表中删除,优化到O(nk). /*hdu6058[链表维护] 2017多效3*/ #inclu ...

  2. hdu-6058 Kanade's sum

    题意:略 思路:要我们求每个区间第K大数之和,其实可以转换为求多少个区间的第K大数是X,然后我们在求和就好了. 那么我们可以从小到大枚举所有可能成为第K大的数.为什么从小到大呢? 因为从小到大我们就略 ...

  3. 【hdu6058】 Kanade's sum 模拟

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题目大意:给你一个$1$到$n$的排列,请求出该序列所有区间中第$k$大之和,若该区间内少于$ ...

  4. 2017 Multi-University Training Contest - Team 3—HDU6058 Kanade's sum

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题目意思:给你一个排列,求所有区间长度大于等于k的区间第k大的数的和…… 思路:一开始看到区间k ...

  5. HDU6058 Kanade's sum(思维 链表)

    Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. 【set】【链表】hdu6058 Kanade's sum

    f(l,r,K)表示区间l,r里面的K大值,问你所有连续子区间的f之和. l(i)表示i左侧第一个比它大的数的位置,r(i)表示i右侧第一个比它大的数的位置.可以用set处理出来. 把数从大到小排序, ...

  7. hdu6058 Kanade's sum 区间第k大

    /** 题目:Kanade's sum 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6058 题意:给定[1,n]的排列,定义f(l,r,k)表示区间[l ...

随机推荐

  1. BZOJ 2502: 清理雪道 | 有上下界最小流

    #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #defi ...

  2. BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】

    题目链接 BZOJ5011 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...

  3. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  4. 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告

    [USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...

  5. JAVA List 一边遍历一边删除元素

    JAVA List 一边遍历一边删除元素,报java.util.ConcurrentModificationException异常 2015年02月10日 14:42:49 zhanzkw 阅读数:3 ...

  6. Java的外部类为什么不能使用private、protected进行修饰

    对于顶级类(外部类)来说,只有两种修饰符:public和默认(default).因为外部类的上一单元是包,所以外部类只有两个作用域:同包,任何位置.因此,只需要两种控制权限:包控制权限和公开访问权限, ...

  7. 安卓tablayout控件的使用

    1.加载依赖 api "com.android.support:design:26.1.0" 2.布局 <android.support.design.widget.TabL ...

  8. deploy a ec2 and join into domain with terraform

    Below is the example to convert the ps script into userdata for terraform to create instance and aut ...

  9. VS2010 VC Project的default Include设置

    在IDE中,打开View->Other Windows->Property Manager.展开树形后,你会发现一个名为“Microsoft.Cpp.Win32.user”的项目(如下图) ...

  10. jzoj2700 【GDKOI2012模拟02.01】数字

    传送门:https://jzoj.net/senior/#main/show/2700 [题目大意] 令n为正整数,S(n)为n的各位数字之和,令