Eterna_King

导航

[NOI2010]超级钢琴

自己演了自己,算错了主席树的空间,然后交上去直接就是个80,然后陷入深思,冷静思考了一会儿,意识到洛谷好像空间开小了会wa,于是加了个5,交上去就过了,以后要好好算空间。

//author Eterna
#define Hello the_cruel_world!
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<utility>
#include<cmath>
#include<climits>
#include<deque>
#include<functional>
#include<complex>
#include<numeric>
#include<unordered_map>
#define Pi acos(-1.0)
#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
#define pb(x) push_back(x)
#define lowbit(x) (x & -x)
#define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin)
#define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define outd(x) printf("%d\n", x)
#define outld(x) printf("%lld\n", x)
#define il inline
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 5e5;
const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const double eps = 1e-7;
inline int read_int() {
    char c;
    int ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
inline ll read_ll() {
    char c;
    ll ret = 0, sgn = 1;
    do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
    if (c == '-') sgn = -1; else ret = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    return sgn * ret;
}
struct node {
    int L, R, cnt;
}arr[25 * maxn + 5];
int T[maxn + 5], tot, sum[maxn + 5], pos[maxn + 5], cnt[maxn + 5], L[maxn + 5], R[maxn + 5];
int Build(int L, int R) {
    int index = ++tot;
    if (L < R) {
        int mid = L + R >> 1;
        arr[index].L = Build(L, mid);
        arr[index].R = Build(mid + 1, R);
    }
    return index;
}
int Update(int pre, int L, int R, int x) {
    int index = ++tot;
    arr[index] = arr[pre];
    ++arr[index].cnt;
    if (L < R) {
        int mid = L + R >> 1;
        if (x <= mid)arr[index].L = Update(arr[pre].L, L, mid, x);
        else arr[index].R = Update(arr[pre].R, mid + 1, R, x);
    }
    return index;
}
int Query(int Left, int Right, int l, int r, int x) {
    if (l >= r)return l;
    int mid = l + r >> 1;
    int cnt = arr[arr[Right].L].cnt - arr[arr[Left].L].cnt;
    if (cnt >= x)return Query(arr[Left].L, arr[Right].L, l, mid, x);
    else return Query(arr[Left].R, arr[Right].R, mid + 1, r, x - cnt);
}
ll res;
priority_queue<pii> q;
int n, k, l, r, m;
int main()
{
    n = read_int() + 1, k = read_int(), l = read_int(), r = read_int();
    L[1] = max(1, 1 - r);
    R[1] = 1 - l;
    for (int i = 2; i <= n; ++i) {
        sum[i] = read_int();
        sum[i] += sum[i - 1];
        pos[i] = sum[i];
        L[i] = max(1, i - r);
        R[i] = i - l;
    }
    sort(pos + 1, pos + 1 + n);
    m = unique(pos + 1, pos + 1 + n) - pos - 1;
    T[0] = Build(1, m);
    for (int i = 1; i <= n; ++i) {
        int x = lower_bound(pos + 1, pos + 1 + m, sum[i]) - pos;
        T[i] = Update(T[i - 1], 1, m, x);
    }
    for (int i = 2; i <= n; ++i) {
        if (L[i] > R[i])continue;
        int x = pos[Query(T[L[i] - 1], T[R[i]], 1, m, 1)];
        cnt[i] = 1;
        q.push(pii(sum[i] - x, i));
    }
    for (int i = 1; i <= k; ++i) {
        pii now = q.top(); q.pop();
        res += now.first;
        int p = now.second;
        ++cnt[p];
        if (cnt[p] > R[p] - L[p] + 1)continue;
        int x = pos[Query(T[L[p] - 1], T[R[p]], 1, m, cnt[p])];
        q.push(pii(sum[p] - x, p));
    }
    cout << res << endl;
    //system("pause");
    return 0;
}
View Code

 

posted on 2019-03-17 16:15  Eterna_King  阅读(115)  评论(0编辑  收藏  举报