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;
}