BZOJ 4504: K个串

Description

兔子们在玩k个串的游戏。首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)。

兔子们想知道,在这个数字序列所有连续的子串中,按照以上方式统计其所有数字之和,第k大的和是多少。

Input

第一行,两个整数n和k,分别表示长度为n的数字序列和想要统计的第k大的和

接下来一行n个数a_i,表示这个数字序列

Output

一行一个整数,表示第k大的和

Sample Input

7 5

3 -2 1 2 2 1 3 -2

Sample Output

4

HINT

1 <= n <= 100000, 1 <= k <= 200000, 0 <= |a_i| <= 10^9数据保证存在第 k 大的和

Solution

麻麻窝再也不用指针了QAQ。。。

root[i]表示以左端点为i的所有区间答案。建立主席树。设next[i]为A[i]下一次出现位置,当我们将i向右移动一位时,i到next[i]-1的答案都要减去A[i]。主席树区间更新,标记下传的时候需要新建节点。每个节点维护最大值和最大值位置。

然后建个堆,push进去以1…n为左端点的答案,每次弹出最大值,在取到最大值的那棵线段树删除这个点,然后push入之后的最大值。弹k次就是答案。

为何heheda神犇跑的飞快QAQ->传送门<-

蒟蒻交了4次还是很慢啊。。

Code

  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
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <cstdio>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const LL INF = (~0ull>>1)-1;
int getint() {
    int r = 0, k = 1; char c = getchar();
    for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
    for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
    return r * k;
}
priority_queue<pair<pair<LL, int>, int> > Q;
const int maxn = 100005;
const int N = maxn * 120;
set<int> M;
map<int, int> h;
int nxt[maxn], tot;
int A[maxn], n, k;
LL laz[N], ans[N], B[maxn];
int lc[N], rc[N], L[N], R[N], pos[N];
int root[maxn];
inline int add(int x, LL val) {
    int ret = ++tot;
    L[ret] = L[x]; R[ret] = R[x];
    lc[ret] = lc[x]; rc[ret] = rc[x];
    ans[ret] = ans[x]; pos[ret] = pos[x];
    laz[ret] = laz[x];
    if (val == -INF) {
        ans[ret] = val;
        laz[ret] = val;
    } else {
        ans[ret] += val;
        laz[ret] += val;
    }
    return ret;
}
inline void pu(int x) {
    if (ans[lc[x]] > ans[rc[x]]) {
        ans[x] = ans[lc[x]];
        pos[x] = pos[lc[x]];
    } else {
        ans[x] = ans[rc[x]];
        pos[x] = pos[rc[x]];
    }
}
inline void pd(int x) {
    if (laz[x]) {
        lc[x] = add(lc[x], laz[x]);
        rc[x] = add(rc[x], laz[x]);
        laz[x] = 0;
    }
}
int build(int l, int r) {
    int ret = ++tot;
    L[ret] = l; R[ret] = r;
    if (l == r) {
        ans[ret] = B[l];
        pos[ret] = l;
        return ret;
    }
    int mid = (l + r) >> 1;
    lc[ret] = build(l, mid);
    rc[ret] = build(mid+1, r);
    pu(ret);
    return ret;
}
int change(int x, int l, int r, LL val) {
    if (l <= L[x] && R[x] <= r) {
        return add(x, val);
    }
    pd(x);
    int ret = ++tot;
    L[ret] = L[x]; R[ret] = R[x];
    lc[ret] = lc[x]; rc[ret] = rc[x];
    ans[ret] = ans[x]; pos[ret] = pos[x];
    int mid = (L[x] + R[x]) >> 1;
    if (l <= mid)
        lc[ret] = change(lc[x], l, r, val);
    if (r > mid)
        rc[ret] = change(rc[x], l, r, val);
    pu(ret);
    return ret;
}
void init() {
    n = getint(); k = getint();
    for (int i = 1; i <= n; ++i) {
        A[i] = getint();
        h[A[i]] = n + 1;
    }
    for (int i = 1; i <= n; ++i) {
        B[i] = B[i-1];
        if (M.find(A[i]) == M.end()) {
            M.insert(A[i]);
            B[i] += A[i];
        }
    }
    for (int i = n; i; --i) {
        nxt[i] = h[A[i]] - 1;
        h[A[i]] = i;
    }
    root[1] = build(1, n);
    for (int i = 1; i < n; ++i) {
        root[i + 1] = change(root[i], i + 1, nxt[i], -A[i]);
        root[i + 1] = change(root[i + 1], i, i, -INF);
    }
    for (int i = 1; i <= n; ++i)
        Q.push(make_pair(make_pair(ans[root[i]], pos[root[i]]), i));
}
int main() {
    init();
    pair<pair<LL, int>, int> now;
    for (int i = 1; i < k; ++i) {
        now = Q.top();
        Q.pop();
        root[now.second] = change(root[now.second], now.first.second, now.first.second, -INF);
        Q.push(make_pair(make_pair(ans[root[now.second]], pos[root[now.second]]), now.second));
    }
    printf("%lld", Q.top().first.first);
    return 0;
}