锣鼓P5356TLE求助!!有没有大佬帮帮我!

题目描述

由乃不太会打扑克

所以她出了一个数据结构题

给你一个长为 n 的序列 a,需要支持 m 次操作,操作有两种:

  1. 查询区间 [l,r] 的第 k 小值。
  2. 区间 [l,r] 加上 k

输入格式

一行两个整数 n,m

接下来一行 n 个整数, 第 i 个整数表示 a_i

接下来 m 行,每行四个数 opt,l,r,k,其中 opt 代表是哪种操作。

输出格式

对于每个询问输出一个数表示答案,如果无解输出 -1

输入输出样例 #1

输入 #1

1 1
1
1 1 1 1

输出 #1

1

说明/提示

1\leq n,m\leq 10^5-2\times 10^4\leq 每次加上的数和原序列的数 \leq 2\times 10^4


\text{upd 2022.8.18}:新增加一组 Hack 数据。

TLE:

#include <iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5, inf = 2e9;
int n, q, num, s;
int a[maxn], t[maxn], belong[maxn], st[maxn], en[maxn], delta[maxn], minv[maxn], maxv[maxn];

inline int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

void write(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

void SORT(int x) {
    int l = st[x], r = en[x];
    for (int i = l; i <= r; ++i) t[i] = a[i];
    sort(t + l, t + r + 1);
    minv[x] = t[l];
    maxv[x] = t[r];
}

int count_less(int w, int l, int r) {
    int x = belong[l], y = belong[r], res = 0;
    if (x == y) {
        for (int i = l; i <= r; ++i)
            if (a[i] + delta[x] < w) res++;
        return res;
    }
    for (int i = l; i <= en[x]; ++i)
        if (a[i] + delta[x] < w) res++;
    for (int i = st[y]; i <= r; ++i)
        if (a[i] + delta[y] < w) res++;
    for (int i = x + 1; i < y; ++i) {
        int target = w - delta[i];
        int cnt = lower_bound(t + st[i], t + en[i] + 1, target) - (t + st[i]);
        res += cnt;
    }
    return res;
}

int main() {
    n = read(); q = read();
    s = 500;
    num = (n + s - 1) / s;
    for (int i = 1; i <= num; ++i) {
        st[i] = (i - 1) * s + 1;
        en[i] = min(i * s, n);
        for (int j = st[i]; j <= en[i]; ++j) belong[j] = i;
    }
    for (int i = 1; i <= n; ++i) a[i] = read();
    for (int i = 1; i <= num; ++i) SORT(i);
    while (q--) {
        int op = read(), l = read(), r = read(), k = read();
        if (op == 2) {
            int x = belong[l], y = belong[r];
            if (x == y) {
                for (int i = st[x]; i <= en[x]; ++i) a[i] += delta[x];
                delta[x] = 0;
                for (int i = l; i <= r; ++i) a[i] += k;
                SORT(x);
            } else {
                for (int i = st[x]; i <= en[x]; ++i) a[i] += delta[x];
                delta[x] = 0;
                for (int i = l; i <= en[x]; ++i) a[i] += k;
                SORT(x);
                for (int i = st[y]; i <= en[y]; ++i) a[i] += delta[y];
                delta[y] = 0;
                for (int i = st[y]; i <= r; ++i) a[i] += k;
                SORT(y);
                for (int i = x + 1; i < y; ++i) delta[i] += k;
            }
        } else {
            if (k > r - l + 1) {
                write(-1); putchar('\n');
                continue;
            }
            int L = inf, R = -inf;
            for (int i = 1; i <= num; ++i) {
                if (en[i] < l || st[i] > r) continue;
                int curr_min = minv[i] + delta[i];
                int curr_max = maxv[i] + delta[i];
                if (curr_min < L) L = curr_min;
                if (curr_max > R) R = curr_max;
            }
            int ans = L - 1;
            while (L <= R) {
                int mid = (0LL + L + R) >> 1;
                int cnt = count_less(mid, l, r);
                if (cnt < k) {
                    ans = mid;
                    L = mid + 1;
                } else {
                    R = mid - 1;
                }
            }
            write(ans); putchar('\n');
        }
    }
    return 0;
}

这题不是暴力能解决的。

建议多做一下符合自己水平的题目。

对不起我菜到啥数据结构都不会,可持久化线段树模版不带修改操作

对不起看错了,我啥数据结构都不会,反正你做不了这道题就对了。

@stringdp100005

语法组萌新题目都读不懂 qwq

so?

@向耕立 e没事,我们两个都是蒟蒻,语法题都不会,请巨佬另找高人。

我是蒟蒻,A+B WA0

没事的我连呼吸都不会

没事我还在我妈妈肚子里

我心脏连跳动都不会

有没有巨佬来帮帮我

这题要分块诶

二分?
image

如果整片 TLE 的话就是你的复杂度有问题,别乱发求调。

@LeuR 建议关帖

建议学完对应算法再来用正解做此题哦,wyy的卡常是没什么用的