QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#645090#7904. Rainbow Subarray666ldcTL 0ms3532kbC++176.2kb2024-10-16 16:51:412024-10-16 16:51:42

Judging History

你现在查看的是最新测评结果

  • [2024-10-16 16:51:42]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:3532kb
  • [2024-10-16 16:51:41]
  • 提交

answer

#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define int long long
#define endl '\n'
using i128 = __int128;
using i64 = long long;
using f128 = long double;
using u64 = unsigned long long;
using pii = pair<int, int>;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const i64 inf = 2e18;
//-------------------------------------------

struct st_tree
{
    int n;
    vector<int> p;
    st_tree(int _n) : p(_n + 1), n(_n) {};

    void init(int _n)
    {
        for (int i = 1; i <= n; i++)
            p[i] = 0;
        n = _n;
    }

    int lowbit(int x)
    {
        return x & -x;
    }

    void add(int u, int d)
    {
        while (u <= n)
            p[u] += d, u += lowbit(u);
    }

    int find(int u)
    {
        int sum = 0;
        while (u > 0)
        {
            sum += p[u], u -= lowbit(u);
        }
        return sum;
    }
};

// root 是最终平衡树,x,y,z记录中间出现的平衡树,idx 是节点编号

struct fhq_treap
{
    struct node
    {
        int l, r, cnt, key, size;
    };
    int x = 0, y = 0, z = 0, root = 0, idx = 0;
    vector<node> fhq;
    fhq_treap(int n) : fhq(n + 1) {};
    int newnode(int cnt)
    {
        fhq[++idx].cnt = cnt;
        fhq[idx].key = rand();
        fhq[idx].size = 1;
        return idx;
    }

    void update(int now)
    {
        fhq[now].size = fhq[fhq[now].l].size + fhq[fhq[now].r].size + 1; // 不要忘记加1 (父节点)
    }

    void spilt(int now, int val, int &x, int &y)
    {
        if (!now)
            x = y = 0;
        else
        {
            if (fhq[now].cnt <= val) // 因为当前节点的值小于val,故当前节点和其全部左子树全部被割个了x
            {
                x = now;
                spilt(fhq[now].r, val, fhq[now].r, y);
            }
            else
            {
                y = now;
                spilt(fhq[now].l, val, x, fhq[now].l);
            }
            update(now);
        }
    }

    int merge(int x, int y) // 注意 y树的所有元素要严格大于x树
    {
        if (!x || !y)
            return x + y;
        else
        {
            if (fhq[x].key <= fhq[y].key) // 无所谓,反正key是随机的
            {
                fhq[y].l = merge(x, fhq[y].l);
                update(y);
                return y;
            }
            else
            {
                fhq[x].r = merge(fhq[x].r, y);
                update(x);
                return x;
            }
        }
    }

    void ins(int val)
    {
        spilt(root, val, x, y);
        root = merge(merge(x, newnode(val)), y);
    }

    void del(int val)
    {
        spilt(root, val, x, y);
        spilt(x, val - 1, x, z); // 此时便把所有等于val的值抛离出来成为z树
        z = merge(fhq[z].l, fhq[z].r);
        root = merge(merge(x, z), y);
    }

    int getrank(int val)
    {
        spilt(root, val - 1, x, y);
        return fhq[x].size + 1;
        root = merge(x, y);
    }

    int getnum(int k)
    {
        int now = root;
        while (now)
        {
            if (fhq[fhq[now].l].size + 1 == k)
                break;
            if (fhq[fhq[now].l].size >= k)
                now = fhq[now].l;
            else
            {
                k -= fhq[fhq[now].l].size + 1; // 不要忘记把根节点减去
                now = fhq[now].r;
            }
        }
        return fhq[now].cnt;
    }

    int pre(int val)
    {
        spilt(root, val - 1, x, y);
        int now = x;
        while (fhq[now].r)
            now = fhq[now].r;
        return fhq[now].cnt;
        root = merge(x, y);
    }

    int nxt(int val)
    {
        spilt(root, val, x, y);
        int now = y;
        while (fhq[now].l)
            now = fhq[now].l;
        return fhq[now].cnt;
        root = merge(x, y);
    }
};

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        a[i] = a[i] - i;
    }

    int num = *min_element(a.begin(), a.end());
    vector<int> hx;
    if (num <= 0)
    {
        num = abs(num);
        for (int i = 1; i <= n; i++)
        {
            a[i] += num + 1;
        }
    }
    hx.push_back(-1);
    for (int i = 1; i <= n; i++)
    {
        hx.push_back(a[i]);
    }
    sort(hx.begin(), hx.end());
    hx.erase(unique(hx.begin(), hx.end()), hx.end());

    auto find = [&](int num)
    {
        return lower_bound(hx.begin(), hx.end(), num) - hx.begin();
    };

    int m = hx.size() - 1;
    st_tree stt(m), cnt(m);

    auto cal = [&](int x, int mid)
    {
        int id = find(x);
        int sum = 0;
        sum += cnt.find(id - 1) * mid - stt.find(id - 1);
        sum += (stt.find(m) - stt.find(id - 1)) - (cnt.find(m) - cnt.find(id - 1)) * mid;
        return sum;
    };

    auto check = [&](int x)
    {
        int sum = 0;
        stt.init(m);
        cnt.init(m);
        fhq_treap fhq(2 * n);
        for (int r = 1; r <= n; r++)
        {
            int id = find(a[r]);
            sum += a[r];
            stt.add(id, a[r]);
            cnt.add(id, 1);
            fhq.ins(a[r]);
            if (r >= x)
            {
                int midl = fhq.getnum(x / 2), midr = fhq.getnum(x / 2 + 1);
                int w = min(cal(midl, midl), cal(midr, midr));
                if (w <= k)
                    return true;
                int id = find(a[r - x + 1]);
                sum -= a[r - x + 1];
                stt.add(id, -a[r - x + 1]);
                cnt.add(id, -1);
                fhq.del(a[r - x + 1]);
            }
        }
        return false;
    };

    int l = 1, r = n;
    while (r > l)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid))
            l = mid;
        else
            r = mid - 1;
    }

    cout << l << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T = 1;
    cin >> T;
    for (int i = 1; i <= T; i++)
        solve();
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3532kb

input:

5
7 5
7 2 5 5 4 11 7
6 0
100 3 4 5 99 100
5 6
1 1 1 1 1
5 50
100 200 300 400 500
1 100
3

output:

4
3
5
1
1

result:

ok 5 lines

Test #2:

score: -100
Time Limit Exceeded

input:

11102
2 167959139
336470888 134074578
5 642802746
273386884 79721198 396628655 3722503 471207868
6 202647942
268792718 46761498 443917727 16843338 125908043 191952768
2 717268783
150414369 193319712
6 519096230
356168102 262263554 174936674 407246545 274667941 279198849
9 527268921
421436316 3613460...

output:

1
4
3
2
6
5
7
2
4
1
4
1
1
3
2
2
7
8
7
7
1
7
6
2
4
3
1
6
7
7
3
4
3
9
3
8
6
6
3
1
6
3
1
2
4
6
4
6
4
1
4
7
1
6
3
5
6
6
1
7
5
3
1
6
4
5
3
2
2
6
2
3
10
1
4
3
2
4
5
1
7
5
5
5
8
5
3
6
3
5
5
8
5
4
5
2
1
5
2
3
3
4
8
1
3
1
2
2
8
3
1
6
8
1
8
4
5
6
6
8
4
8
3
2
8
4
5
6
2
6
2
4
1
5
4
5
3
2
4
1
2
1
4
5
8
3
7
3
3
3...

result: