P3372 【模板】线段树 1

联系splay ing!

这道题最好当然是用线段树写咯,但是平衡树什么东西都能维护,包括区间加,不如写一写练练手。

下放lazy的时候sum应该加上lazy的size倍,不需要用什么l和r来维护。

代码:

#include<cstdio>
#define ll long long

const int maxn = 100005;
ll size[maxn], fa[maxn], ch[maxn][2], val[maxn];
ll sum[maxn], lazy[maxn];
ll root;
ll a[maxn];
ll n, m;
int dir(ll x)
{
    return ch[fa[x]][1] == x;
}
void connect(ll son, ll f, ll k)
{
    fa[son] = f;
    ch[f][k] = son;
}
void pushup(ll x)
{
    size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
    sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + val[x];
}
void pushdown(ll x)
{
    if(lazy[x] != 0)
    {
        val[ch[x][0]] += lazy[x];
        sum[ch[x][0]] += size[ch[x][0]] * lazy[x];
        lazy[ch[x][0]] += lazy[x];
        val[ch[x][1]] += lazy[x];
        sum[ch[x][1]] += size[ch[x][1]] * lazy[x];
        lazy[ch[x][1]] += lazy[x];
        lazy[x] = 0;
    }
}
void rotate(ll x)
{
    ll y = fa[x];
    ll z = fa[y];
    int yk = dir(x);
    int zk = dir(y);
    ll b = ch[x][yk ^ 1];
    connect(b, y, yk);
    connect(y, x, yk ^ 1);
    connect(x, z, zk);
    pushup(y);
    pushup(x);
}
void splay(ll x, ll goal)
{
    while(fa[x] != goal)
    {
        ll y = fa[x];
        ll z = fa[y];
        if(z != goal) dir(x) == dir(y) ? rotate(y) : rotate(x);
        rotate(x);
    }
    if(goal == 0) root = x;
}
ll kth(ll k)
{
    ll now = root;
    while(233)
    {
        pushdown(now);
        if(size[ch[now][0]] + 1 < k)
        {
            k -= size[ch[now][0]] + 1;
            now = ch[now][1];
        }
        else if(size[ch[now][0]] >= k) now = ch[now][0];
        else return now;
    }
}
ll build(ll f, ll l, ll r)// maybe need array "id"
{
    if(l > r) return 0;
    if(l == r)
    {
        size[l] = 1;
        val[l] = sum[l] = a[l];
        fa[l] = f;
        return l;
    }
    int mid = (l + r) >> 1;
    val[mid] = a[mid];
    fa[mid] = f;
    ch[mid][0] = build(mid, l, mid - 1);
    ch[mid][1] = build(mid, mid + 1, r);
    pushup(mid);
    return mid;
}
ll split(ll x, ll y)
{
    ll pre = kth(x), post = kth(y + 2);
    splay(pre, 0), splay(post, pre);
    return ch[post][0];
}
void print(ll u)
{
    pushdown(u);
    if(ch[u][0]) print(ch[u][0]);
    printf("%lld ", val[u]);
    if(ch[u][1]) print(ch[u][1]);
}
ll read()
{
    ll ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    return s * ans;
}
int main()
{
    n = read(), m = read();
    for(int i = 2; i <= n + 1; i++) a[i] = read();
    root = build(0, 1, n + 2);
    while(m--)
    {
        int opt = read();
        ll x = read(), y = read(), k;
        if(opt == 1)
        {
            k = read();
            ll del = split(x, y);
            val[del] += k;
            sum[del] += size[del] * k;
            lazy[del] += k;
        }
        else if(opt == 2)
        {
            ll del = split(x, y);
            printf("%lld\n", sum[del]);
        }
        //print(root); printf("\n");
    }
    return 0;
}
posted @ 2018-09-08 12:58  Garen-Wang  阅读(136)  评论(0编辑  收藏  举报