“老早老早以前就A掉了~”
就是那么“老早”以前的题,今天又一次拿出来做了,不过换了一种数据结构,用的是标题里说的“传说中的无与伦比的Splay-Tree”的数据结构。
主要是上次心血来潮了,所以就决定学splay,于是乎又重新拿出了胡浩神牛的那份模板开始改起来了,不过,还是没改成功。。。
最后,只能问超哥要了代码,然后开始改超哥的模板(其实是超哥将胡浩的代码改过来的),最后改成自己喜欢的套路。。。好吧,其实就是。。。很简单的改了一下,灰常没有技术含量。。。
最后虽然是用splay水了几道线段树的题,但是,其实没有搞懂代码的意思。。。。算了,反正就这样了吧~
附上代码:
#include
#include
#include
using namespace std;
#define Maxn 2000000
#define keyTree (edge[edge[root].ch[1]].ch[0])
//keytree是要 求的区间[a,b]
#pragma comment(linker, "/STACK:102400000,102400000")
typedef __int64 LL;
struct Node {
int ch[2], pre, sz;
LL val, sum, add;
//ch[root][0]表示root的左儿子地址,ch[root][1]表示root的右儿子地址
//pre[root]表示root的父亲
//sz[root]表示他和他儿子的个数,这颗子树的大小
//val[root]表示这个节点的值
} edge[Maxn];
int root, id;
LL a[Maxn];
void push_up(int x) {//延迟向上更新
edge[x].sz = 1 + edge[edge[x].ch[0]].sz + edge[edge[x].ch[1]].sz;
edge[x].sum = edge[edge[x].ch[0]].sum + edge[edge[x].ch[1]].sum + edge[x].val;
}
void push_down(int x) {//延迟向下更新 x是当前节点的内存块
edge[x].val += edge[x].add;
edge[edge[x].ch[0]].add += edge[x].add;
edge[edge[x].ch[0]].sum += edge[edge[x].ch[0]].sz * edge[x].add;
edge[edge[x].ch[1]].add += edge[x].add;
edge[edge[x].ch[1]].sum += edge[edge[x].ch[1]].sz * edge[x].add;
edge[x].add = 0;
}
void Rotate(int x, int f) {
int y = edge[x].pre;
push_down(y);
push_down(x);
edge[y].ch[!f] = edge[x].ch[f];
edge[edge[x].ch[f]].pre = y;
edge[x].pre = edge[y].pre;
if (edge[y].pre) {
edge[edge[y].pre].ch[edge[edge[y].pre].ch[1] == y] = x;
}
edge[x].ch[f] = y;
edge[y].pre = x;
push_up(y);
}
void Splay(int x, int goal) {//把x旋转到goal下面去,x比goal小就左边
push_down(x); //
while (edge[x].pre != goal) {
if (edge[edge[x].pre].pre == goal) {
Rotate(x, edge[edge[x].pre].ch[0] == x);
} else {
int y = edge[x].pre, z = edge[y].pre;
int f = (edge[z].ch[0] == y);
if (edge[y].ch[f] == x) {
Rotate(x, !f), Rotate(x, f);
} else {
Rotate(y, f), Rotate(x, f);
}
}
}
push_up(x);
if (goal == 0)root = x;
}
void RotateTo(int k, int goal) {//找第k个数,并把它旋转到goal下面
int x = root;
push_down(x);
while (edge[edge[x].ch[0]].sz != k) {
if (k < edge[edge[x].ch[0]].sz) {
x = edge[x].ch[0];
} else {
k -= (edge[edge[x].ch[0]].sz + 1);
x = edge[x].ch[1];
}
push_down(x);
}
Splay(x, goal);
}
void NewNode(int &x, LL c, int fa) {//新建一个节点
x = ++id;
edge[x].ch[0] = edge[x].ch[1] = 0;
edge[x].pre = fa;
edge[x].sz = 1, edge[x].val = c;
edge[x].sum = edge[x].add = 0;
}
void MakeTree(int &x, int L, int R, int fa) {//x表示当前节点,建这颗平衡树
if (L > R)return;
int mid = (L + R) >> 1;
NewNode(x, a[mid], fa);
MakeTree(edge[x].ch[0], L, mid - 1, x);
MakeTree(edge[x].ch[1], mid + 1, R, x);
push_up(x); //把两个儿子凑起来
}
void Init(int n) {//
root = id = 0;
NewNode(root, -1, 0);
NewNode(edge[root].ch[1], -1, root);
MakeTree(keyTree, 1, n, edge[root].ch[1]);
push_up(edge[root].ch[1]);
push_up(root);
}
void Insert(int L, int R, int x) {//在L-R之间插入一个数
RotateTo(L, 0);
RotateTo(R, root);
NewNode(keyTree, x, edge[root].ch[1]);
push_up(edge[root].ch[1]);
push_up(root);
}
void Delete(int L, int R) {//删掉
RotateTo(L, 0);
RotateTo(R, root);
keyTree = 0;
push_up(edge[root].ch[1]);
push_up(root);
}
int main() {
int i, j, n, m;
while (scanf("%d%d", &n, &m) != EOF) {
for (i = 1; i <= n; i++) {
scanf("%I64d", &a[i]);
}
Init(n);
while (m--) {
char st[10];
int left, right;
LL val;
scanf("%s", st);
if (st[0] == 'Q') {
scanf("%d%d", &left, &right);
RotateTo(left - 1, 0);
RotateTo(right + 1, root);
cout << edge[keyTree].sum << endl;
} else {
scanf("%d%d%I64d", &left, &right, &val);
RotateTo(left - 1, 0);
RotateTo(right + 1, root);
edge[keyTree].add += val;
edge[keyTree].sum += val * edge[keyTree].sz;
}
}
}
return 0;
}