POJ_3468 (2)
第三次写这个题了,不过这次写的挺痛苦的,也是为了练基本的splay对区间的操作,不过写得比较挫……
不过通过这次写splay的代码,感觉论文上rotate操作里面的push_down下传标记的操作是没有用的,因为调用rotate_to找对应节点的时候已经把标记都下传好了,而rotate操作也只是对rotate_to走过的路径上节点进行操作,因此该下传的就早已在调用rotate_to的时候下传完毕了。
#include<stdio.h>
#include<string.h>
#define MAXD 100010
int N, Q, T, node, left[MAXD], right[MAXD], size[MAXD], pre[MAXD], a[MAXD];
long long int key[MAXD], add[MAXD], sum[MAXD];
void update(int &T)
{
sum[T] = sum[left[T]] + sum[right[T]] + key[T];
size[T] = size[left[T]] + size[right[T]] + 1;
}
void push_down(int &T)
{
key[T] += add[T];
if(left[T])
{
add[left[T]] += add[T];
sum[left[T]] += size[left[T]] * add[T];
}
if(right[T])
{
add[right[T]] += add[T];
sum[right[T]] += size[right[T]] * add[T];
}
add[T] = 0;
}
void left_rotate(int x)
{
int y = right[x], p = pre[x];
right[x] = left[y];
if(right[x])
pre[right[x]] = x;
left[y] = x;
pre[x] = y;
pre[y] = p;
if(p != 0)
right[p] == x ? right[p] = y : left[p] = y;
else
T = y;
update(x);
}
void right_rotate(int x)
{
int y = left[x], p = pre[x];
left[x] = right[y];
if(left[x])
pre[left[x]] = x;
right[y] = x;
pre[x] = y;
pre[y] = p;
if(p != 0)
right[p] == x ? right[p] = y : left[p] = y;
else
T = y;
update(x);
}
void new_node(int &T, int v)
{
T = ++ node;
size[T] = 1;
key[T] = v;
add[T] = 0;
left[T] = right[T] = 0;
}
void build(int &T, int x, int y, int fa)
{
int mid = (x + y) / 2;
new_node(T, a[mid]), pre[T] = fa;
if(x < mid)
build(left[T], x, mid - 1, T);
if(mid < y)
build(right[T], mid + 1, y, T);
update(T);
}
void init()
{
int i, j, k;
for(i = 1; i <= N; i ++)
scanf("%d", &a[i]);
T = node = left[0] = right[0] = size[0] = key[0] = add[0] = sum[0] = 0;
new_node(T, 0), new_node(right[T], 0);
pre[T] = 0, pre[right[T]] = T;
size[T] = 2;
build(left[right[T]], 1, N, right[T]);
update(right[T]), update(T);
}
void splay(int x, int goal)
{
int y, z;
for(;;)
{
if((y = pre[x]) == goal)
break;
if((z = pre[y]) == goal)
right[y] == x ? left_rotate(y) : right_rotate(y);
else
{
if(right[z] == y)
{
if(right[y] == x)
left_rotate(z), left_rotate(y);
else
right_rotate(y), left_rotate(z);
}
else
{
if(left[y] == x)
right_rotate(z), right_rotate(y);
else
left_rotate(y), right_rotate(z);
}
}
}
update(x);
}
void rotate_to(int k, int goal)
{
int i = T, n;
for(;;)
{
push_down(i);
n = size[left[i]] + 1;
if(k == n)
break;
if(k < n)
i = left[i];
else
{
k -= n;
i = right[i];
}
}
splay(i, goal);
}
void query(int x, int y)
{
rotate_to(x, 0), rotate_to(y + 2, T);
printf("%lld\n", sum[left[right[T]]]);
}
void refresh(int x, int y, int z)
{
rotate_to(x, 0), rotate_to(y + 2, T);
int k = left[right[T]];
add[k] += z, sum[k] += z * size[k];
}
void solve()
{
int i, j, k, x, y, z;
char b[5];
for(i = 0; i < Q; i ++)
{
scanf("%s", b);
if(b[0] == 'Q')
{
scanf("%d%d", &x, &y);
query(x, y);
}
else
{
scanf("%d%d%d", &x, &y, &z);
refresh(x, y, z);
}
}
}
int main()
{
while(scanf("%d%d", &N, &Q) == 2)
{
init();
solve();
}
return 0;
}