POJ3468 A Simple Problem with Integers

我不是code的生产者,我只是code的搬运工。(咱们码农有力量!)

全当学写lazy标记了= =


PS:说到这个lazy标记,从线段树开始我就不会lazy标记啊,直接导致我一年来再也不写线段树了= =(还好我有两个线段树达人队友,妈妈再也不用担心我的线段树了~)


#include <cstdio>
using namespace std;
typedef long long ll;

const int maxn = 100010;
int n, q, a[maxn];
int val[maxn], fa[maxn], ch[maxn][2], size[maxn], root, tot;
int add[maxn];
ll sum[maxn];

void init()
{
    root = tot = 0;
    val[0] = fa[0] = ch[0][0] = ch[0][1] = size[0] = 0;
    add[0] = sum[0] = 0;
}

void newnode(int &x, int value, int father)
{
    x = ++tot;
    val[x] = value;
    fa[x] = father;
    ch[x][0] = ch[x][1] = 0;
    size[x] = 1;
    add[x] = 0;
    sum[x] = value;
}

void push_down(int x)
{
    if (!add[x]) return;
    val[x] += add[x];
    add[ch[x][0]] += add[x]; add[ch[x][1]] += add[x];
    sum[ch[x][0]] += (ll)add[x] * size[ch[x][0]]; sum[ch[x][1]] += (ll)add[x] * size[ch[x][1]];
    add[x] = 0;
}

void push_up(int x)
{
    size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
    sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + val[x] + add[x];
}

void rotate(int x, int kind)
{
    int y = fa[x];
    push_down(x); push_down(y);
    ch[y][kind^1] = ch[x][kind];
    fa[ch[x][kind]] = y;
    if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y] = x;
    fa[x] = fa[y];
    ch[x][kind] = y;
    fa[y] = x;
    push_up(y);
}

void splay(int x, int goal)
{
    push_down(x);
    while (fa[x] != goal)
    {
        int y = fa[x];
        if (fa[y] == goal) rotate(x, ch[y][0]==x);
        else
        {
            int kind = ch[fa[y]][0]==y;
            if (ch[y][kind] == x) {rotate(x, kind^1); rotate(x, kind);}
            else {rotate(y, kind); rotate(x, kind);}
        }
    }
    push_up(x);
    if (goal == 0) root = x;
}

void rotateto(int k, int goal) // 第k位的数
{
    int x = root;
    push_down(x);
    while (size[ch[x][0]] != k-1)
    {
        if (size[ch[x][0]] >= k) x = ch[x][0];
        else
        {
            k -= size[ch[x][0]] + 1;
            x = ch[x][1];
        }
        push_down(x);
    }
    splay(x, goal);
}

bool insert(int value)
{
    int x = root;
    if (val[x] == value) return 0;
    while (ch[x][val[x]<value])
    {
        x = ch[x][val[x]<value];
        if (val[x] == value) {splay(x, 0); return 0;}
    }
    newnode(ch[x][val[x]<value], value, x);
    splay(ch[x][val[x]<value], 0);
    return 1;
}

void build(int &x, int l, int r, int father)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, a[mid], father);
    if (l < mid) build(ch[x][0], l, mid-1, x);
    if (mid < r) build(ch[x][1], mid+1, r, x);
    push_up(x);
}

int main()
{
    while (scanf("%d%d", &n, &q) == 2)
    {
        for (int i=1;i<=n;i++) scanf("%d", &a[i]);

        init();
        newnode(root, -1, 0);
        newnode(ch[root][1], -1, root);
        size[root] = 2;
        build(ch[ch[root][1]][0], 1, n, ch[root][1]);
        push_up(ch[root][1]);
        push_up(root);

        while (q--)
        {
            char cmd[3];
            int l, r;
            scanf("%s%d%d", cmd, &l, &r);
            rotateto(l, 0);
            rotateto(r+2, root);
            if (cmd[0] == 'Q')
            {
                printf("%lld\n", sum[ch[ch[root][1]][0]]);
            }
            else
            {
                int d;
                scanf("%d", &d);
                add[ch[ch[root][1]][0]] += d;
                sum[ch[ch[root][1]][0]] += size[ch[ch[root][1]][0]] * d;
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值