P5494 【模板】线段树分裂

真的是看到眼都瞎了也没看出哪里错了来。。。
最后还是看出来了,pos==4的时候忘了写else。。。

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#define ll long long
#define int ll
using namespace std;
const int maxn = 601000;

struct node
{
    int lc, rc, sum;
}t[maxn<<2];

int rt[maxn], st[maxn << 2], a[maxn], top, cnt;

int newnode(void)
{
    int p = 0;
    if (top) p = st[top--];
    else p = ++cnt;
    t[p].lc = t[p].rc = t[p].sum = 0;
    return p;
}

void pushup(int p)
{
    t[p].sum = t[t[p].lc].sum + t[t[p].rc].sum;
}

void del(int &p)
{
    st[++top] = p;
    t[p].lc = t[p].rc = t[p].sum = 0;
    p = 0;
}

void build(int& p, int l, int r)
{
    if (!p) p = newnode();
    if (l == r)
    {
        t[p].sum = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(t[p].lc, l, mid);
    build(t[p].rc, mid + 1, r);
    pushup(p);
}

void split(int& p1, int& p2, int askl, int askr, int l, int r)
{
    if (!p1) return;
    if (askl <= l && r <= askr)
    {
        p2 = p1;
        p1 = 0;
        return;
    }
    if (!p2) p2 = newnode();
    int mid = (l + r) >> 1;
    if (mid >= askl) split(t[p1].lc, t[p2].lc, askl, askr, l, mid);
    if (mid + 1 <= askr) split(t[p1].rc, t[p2].rc, askl, askr, mid + 1, r);
    
    pushup(p1), pushup(p2);
}

void _merge(int &p, int &q, int l, int r)
{
    if (!p || !q)
    {
        if (!p) p = q;
        return;
    }
    if (l == r)
    {
        t[p].sum += t[q].sum;
        del(q);
        return ;
    }
    int mid = (l + r) >> 1;
     _merge(t[p].lc, t[q].lc, l, mid);
     _merge(t[p].rc, t[q].rc, mid + 1, r);
    pushup(p);
    del(q);
    return ;
}

void change(int& p, int l, int r, int pos,int val)
{
    if (!p) p = newnode();
    if (l == r)
    {
        t[p].sum += val;
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) change(t[p].lc, l, mid, pos, val);
    else change(t[p].rc, mid + 1, r, pos, val);
    pushup(p);
}

int ask(int p, int askl, int askr, int l, int r)
{
    if (!p) return 0;
    if (askl <= l && r <= askr)
        return t[p].sum;
    int mid = (l + r) >> 1, ans = 0;
    if (mid >= askl)ans += ask(t[p].lc, askl, askr, l, mid);
    if (mid + 1 <= askr) ans += ask(t[p].rc, askl, askr, mid + 1, r);
    return ans;
}

int ask(int p, int l, int r, int k)
{
    if (l == r)
        return l;
    int mid = (l + r) >> 1;
    if (t[t[p].lc].sum >= k) return ask(t[p].lc, l, mid, k);
    else return ask(t[p].rc, mid + 1, r, k - t[t[p].lc].sum);
}

signed main(void)
{
    int n, m;
    int pos, p, x, y, q, k, cntp = 1;
    scanf("%lld%lld", &n, &m);
    for (int i = 1;i <= n;i++)
        scanf("%lld", &a[i]);

    build(rt[1], 1, n);

    for (int i = 1;i <= m;i++)
    {
        scanf("%lld", &pos);
        if (pos == 0)
        {
            scanf("%lld%lld%lld", &p, &x, &y);
            split(rt[p], rt[++cntp], x, y, 1, n);
        }
        else if (pos == 1)
        {
            scanf("%lld%lld", &p, &q);
            _merge(rt[p], rt[q], 1, n);
        }
        else if (pos == 2)
        {
            scanf("%lld%lld%lld", &p, &x, &q);
            change(rt[p], 1, n, q, x);
        }
        else if (pos == 3)
        {
            scanf("%lld%lld%lld", &p, &x, &y);
            printf("%lld\n", ask(rt[p], x, y, 1, n));
        }
        else if (pos == 4)
        {
            scanf("%lld%lld", &p, &k);
            if (t[rt[p]].sum < k || k <= 0) printf("-1\n");
            else printf("%lld\n", ask(rt[p], 1, n, k));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值