题意:
n个数,有两种操作,一种是查询区间和,另一种是在区间上每一个数加上v。
把bake爷的数组版改造成了结构体版。。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define ll long long
#define N 100105
#define inf 100000000
#define L(id) tree[id].ch[0]
#define R(id) tree[id].ch[1]
#define Father(id) tree[id].fa
#define Mid(x,y) ((x+y)>>1)
ll num[N];//序列
struct Node{
ll ch[2], fa, size;
ll val, sum, add;
}tree[N];
ll tot, root;
void Newnode(ll& id, ll fa, ll val){
id = ++tot;
Father(id) = fa;
tree[id].sum = tree[id].val = val;
tree[id].add = 0;
tree[id].size = 1;
L(id) = R(id) = 0;
}
void push_down(ll id){
if(tree[id].add)
{
tree[id].val += tree[id].add;
tree[L(id)].sum += tree[id].add * tree[L(id)].size;
tree[R(id)].sum += tree[id].add * tree[R(id)].size;
tree[L(id)].add += tree[id].add;
tree[R(id)].add += tree[id].add;
tree[id].add = 0;
}
}
void push_up(ll id){
tree[id].size = tree[L(id)].size+tree[R(id)].size +1;
tree[id].sum = tree[L(id)].sum+tree[R(id)].sum + tree[id].val;
}
void rotate(ll id,ll kind){ //kind=0表示左旋,kind=1表示右旋
ll y = Father(id);
push_down(id); push_down(y);
tree[y].ch[kind^1] = tree[id].ch[kind];
Father( tree[id].ch[kind] ) = y;
if(Father(y))
tree[Father(y)].ch[R(Father(y))==y] = id;
Father(id) = Father(y);
tree[id].ch[kind] = y;
Father(y) = id;
push_up(y);
}
void splay(ll id, ll goal){
push_down(id);
while(Father(id) != goal)
{
if(Father( Father(id) ) == goal)
rotate(id,L( Father(id) ) == id);
else
{
int y = Father(id); //y为父节点
int kind = L( Father(y) ) == y;
if(tree[y].ch[kind] == id)
{
rotate(id,kind^1);
rotate(id,kind);
}
else
{
rotate(y,kind);
rotate(id,kind);
}
}
}
push_up(id);
if(goal == 0) root = id;
}
void rotateto(ll k, ll goal){ //把第k个节点转到goal下
ll id = root;
push_down(id);
while(tree[L(id)].size != k)
{
if(tree[L(id)].size > k)
id = L(id);
else
{
k -= (tree[L(id)].size + 1);
id = R(id);
}
push_down(id);
}
splay(id, goal);
}
ll query(ll l, ll r){
rotateto(l-1, 0);
rotateto(r+1, root);
return tree[L( R(root) )].sum;
}
void update(ll l, ll r, ll v){
rotateto(l-1, 0);
rotateto(r+1,root);
ll tmp = L( R(root) );
tree[tmp].add += v;
tree[tmp].sum += (ll)tree[tmp].size*v;
}
void build(ll l, ll r, ll& id, ll fa){
if(l > r)return ;
int mid = Mid(l,r);
Newnode(id,fa,num[mid]);
build(l,mid-1,L(id),id);
build(mid+1,r,R(id),id);
push_up(id);
}
ll n, q;
void init(){
for(ll i = 0; i < n; i++)scanf("%lld",&num[i]);
root = tot = 0;
Father(0) = L(0) = R(0) = tree[0].size = 0;
tree[0].sum = tree[0].val = 0;
Newnode(root, 0, -1);
Newnode(R(root), root, -1);
tree[root].size = 2;
build(0, n-1, L( R(root) ), R(root));
push_up(R(root));
push_up(root);
}
int main(){
ll l, r, v;
char str[5];
scanf("%lld %lld",&n,&q);
init();
while(q--){
scanf("%s",str);
scanf("%lld%lld",&l,&r);
if(str[0] == 'Q')
printf("%lld\n",query(l,r));
else
{
scanf("%lld",&v);
update(l,r,v);
}
}
return 0;
}