题解
Splay入门模板
将l - 1移到根, r + 1移到根下方, 那么[l, r]就在根的右子树的左子树上, 更新的时候也这样旋转, 更新lazy
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define debug 0
#define M(a, b) memset(a, b, sizeof(a))
#define ls ch[x][0]
#define rs ch[x][1]
const int maxn = (1e5 + 10);
struct Splay{
int pre[maxn], ch[maxn][2], sz[maxn], v[maxn];
int add[maxn], a[maxn];
int root, rt;
long long sum[maxn];
Splay() {
root = rt = 0;
M(pre, 0);
M(ch, 0);
M(sz, 0);
M(v, 0);
M(sum, 0);
M(add, 0);
}
void newNode(int &x, int c) {//新建节点
x = ++rt;
sz[x] = 1;
v[x] = sum[x] = c;
}
void pushDown(int x) {//下移
if (add[x]) {
v[x] += add[x];
add[ls] += add[x];
add[rs] += add[x];
sum[ls] += (long long)sz[ls] * add[x];
sum[rs] += (long long )sz[rs] * add[x];
add[x] = 0;
}
}
void pushUp(int x) {//向上传递
sz[x] = sz[ls] + sz[rs] + 1;
sum[x] = sum[ls] + sum[rs] + v[x];
}
void Rotate(int x, int d) {//旋转
int y = pre[x];
pushDown(y);
pushDown(x);
ch[y][!d] = ch[x][d];
pre[ch[y][!d]] = y;
pre[x] = pre[y];
ch[x][d] = y;
if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
pre[y] = x;
pushUp(y);
}
void splay(int x, int to) {//转到
while (pre[x] != to) {
if (pre[pre[x]] == to) Rotate(x, ch[pre[x]][0] == x);
else {
int y = pre[x], z = pre[y];
int f = (ch[z][1] == y);
if (ch[y][f] == x)
Rotate(y, !f), Rotate(x, !f);
else
Rotate(x, f), Rotate(x, !f);
}
}
pushUp(x);
if (!to) root = x;
}
void RotateTo(int k, int to) {
int x = root;
pushDown(x);
while (sz[ls] != k) {
if (sz[ls] < k) {
k -= sz[ls] + 1;
x = rs;
}
else {
x = ls;
}
pushDown(x);//要旋转在查找时要下移
}
splay(x, to);
}
void build(int &x, int l, int r, int f) {
if (l > r) return;
int mid = (l + r) >> 1;
newNode(x, a[mid]);
build(ls, l, mid - 1, x);
build(rs, mid + 1, r, x);
pre[x] = f;
pushUp(x);
}
void init(int n) {
newNode(root, -1);//加两个节点, 去除冗余信息
newNode(ch[root][1], -1);
pre[rt] = root;
sz[root] = 2;
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
build(ch[ch[root][1]][0], 0, n - 1, ch[root][1]);//建树, 保证中序遍历一致
pushUp(ch[root][1]);//传递
pushUp(root);
}
void update(int l, int r, int val) {
RotateTo(l - 1, 0);
RotateTo(r + 1, root);
add[ch[ch[root][1]][0]] += val;
sum[ch[ch[root][1]][0]] += (long long )val * sz[ch[ch[root][1]][0]];//[l, r]lazy
}
long long query(int l, int r) {
RotateTo(l - 1, 0);
RotateTo(r + 1, root);
return sum[ch[ch[root][1]][0]];
}
}sp;
int main() {
#if debug
freopen("in.txt", "r", stdin);
#endif //debug
//cin.tie(0);
//cin.sync_with_stdio(false);
int n, m, l, r, c;
char s[5];
while (~scanf("%d%d", &n, &m)) {
sp.init(n);
while (m--) {
scanf("%s%d%d", s, &l, &r);
if (s[0] == 'Q') printf("%I64d\n", sp.query(l, r));
else {
scanf("%d", &c);
sp.update(l, r, c);
}
}
}
return 0;
}