#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100010
#define inf 0x3f3f3f3f
#define LL long long int
#define Key_value ch[ch[root][1]][0]
int pre[maxn],key[maxn],ch[maxn][2],root,tot1;
int size[maxn],s[maxn],tot2,val[maxn];
int add[maxn];
LL sum[maxn];
int n,q;
void NewNode(int & r,int father,int k)
{
if(tot2)
r = s[--tot2];
else
r = ++tot1;
pre[r] = father;
val[r] = k;
sum[r] = k;
add[r] = 0;
size[r] = 1;
ch[r][0] = ch[r][1] = 0;
}
//将延迟标记更新到孩子结点
void PushDown(int r)
{
if(add[r])
{
val[r] += add[r];
add[ch[r][0]] += add[r];
add[ch[r][1]] += add[r];
sum[ch[r][0]] += (LL)add[r]*size[ch[r][0]];
sum[ch[r][1]] += (LL)add[r]*size[ch[r][1]];
add[r] = 0;
}
}
//通过孩子结点更新父结点
void PushUp(int r)
{
size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;
sum[r] = sum[ch[r][0]] + sum[ch[r][1]] + val[r] + add[r];
}
//旋转,kind为1为右旋,kind为0为左旋
void Rotate(int x,int kind)
{
int y = pre[x];
PushDown(y);
PushDown(x);
//类似SBT,要把其中一个分支先给父结点
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
//如果父结点不是根结点,则要和父结点的父结点连接起来
if(pre[y])
ch[pre[y]][ch[pre[y]][1] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
PushUp(y);
//PushUp(x);
}
void Splay(int r,int goal)
{
PushDown(r);
while(pre[r] != goal)
{
//父结点即是目标位置,goal为0表示,父结点就是根节点
if(pre[pre[r]] == goal)
Rotate(r,ch[pre[r]][0]==r);
else
{
int y = pre[r];
int kind = ch[pre[y]][0] == y;
//两个方向不同,则先左旋再右旋
if(ch[y][kind] == r)
{
Rotate(r,!kind);
Rotate(r,kind);
}
//两个方向相同,相同方向连续两次
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
PushUp(r);
//更新根节点
if(goal == 0) root = r;
}
//把第k位的数转到goal下边
void RotateTo(int k,int goal)
{
int r = root;
PushDown(r);
while(size[ch[r][0]] != k)
{
if(k < size[ch[r][0]])
r = ch[r][0];
else
{
k -= (size[ch[r][0]] + 1);
r = ch[r][1];
}
PushDown(r);
}
Splay(r,goal);
}
int Insert(int k)
{
int r = root;
while(ch[r][key[r]<k])
r = ch[r][key[r] < k];
NewNode(ch[r][k>key[r]],r,k);
Splay(ch[r][k>key[r]],0);
return 1;
}
//找前驱,即左子树的最右结点
int get_pre(int x)
{
int tmp = ch[x][0];
if(tmp == 0) return inf;
while(ch[tmp][1])
tmp = ch[tmp][1];
return key[x] - key[tmp];
}
//找后继,即右子树的最左结点
int get_next(int x)
{
int tmp = ch[x][1];
if(tmp == 0) return inf;
while(ch[tmp][0])
tmp = ch[tmp][0];
return key[tmp] - key[x];
}
//查询[l,r]之间的和
LL Query(int l,int r)
{
RotateTo(l-1,0);
RotateTo(r+1,root);
return sum [Key_value];
}
//更新
void Update(int l,int r)
{
int k;
scanf("%d",&k);
RotateTo(l-1,0);
RotateTo(r+1,root);
add[Key_value] += k;
sum[Key_value] += size[Key_value]*k;
}
int a[maxn];
//建树,中间结点先建立,然后分别对区间两端在左右子树建立
void BuildTree(int &x,int l,int r,int father)
{
if(l > r)
return;
int mid = (l+r)/2;
NewNode(x,father,a[mid]);
if(l < mid)
BuildTree(ch[x][0],l,mid-1,x);
if(r > mid)
BuildTree(ch[x][1],mid+1,r,x);
PushUp(x);
}
void Init()
{
for(int i = 0;i < n;i++)
scanf("%d",&a[i]);
ch[0][0] = ch[0][1] = pre[0] = size[0] = 0;
add[0] = sum[0] = 0;
root = tot1 = 0;
NewNode(root,0,-1);
NewNode(ch[root][1],root,-1);
size[root] = 2;
BuildTree(Key_value,0,n-1,ch[root][1]);//让所有数据夹在两个-1之间
PushUp(ch[root][1]);
PushUp(root);
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
Init();
while(q--)
{
char str[10];
int x,y;
scanf("%s%d%d",str,&x,&y);
if(str[0] == 'Q')
printf("%lld\n",Query(x,y));
else
Update(x,y);
}
}
return 0;
}
风格更新后:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 100010
#define LL long long int
#define Key_value ch[ch[root][1]][0]
inline int min(int a,int b)
{
return a>b?b:a;
}
struct SplayTree
{
int pre[maxn],key[maxn],ch[maxn][2],size[maxn],add[maxn],a[maxn],root,cnt;
LL sum[maxn];
void init(int n)
{
root = cnt = 0;
ch[0][0] = ch[0][1] = pre[0] = size[0] = key[0] = 0;
add[0] = sum[0] = 0;
NewNode(root,0,-1);
NewNode(ch[root][1],root,-1);
size[root] = 2;
BuildTree(Key_value,0,n-1,ch[root][1]);
PushUp(ch[root][1]);
PushUp(root);
}
void BuildTree(int & x,int l,int r,int father)
{
if(l > r) return;
int mid = (l+r) >> 1;
NewNode(x,father,a[mid]);
if(l < mid)
BuildTree(ch[x][0],l,mid-1,x);
if(r > mid)
BuildTree(ch[x][1],mid+1,r,x);
PushUp(x);
}
void NewNode(int & r,int father,int k)
{
r = ++cnt;
pre[r] = father;
ch[r][0] = ch[r][1] = 0;
key[r] = sum[r] = k;
add[r] = 0;
size[r] = 1;
}
void PushDown(int r)
{
if(add[r])
{
key[r] += add[r];
add[ch[r][0]] += add[r];
add[ch[r][1]] += add[r];
sum[ch[r][0]] += (LL)add[r]*size[ch[r][0]];
sum[ch[r][1]] += (LL)add[r]*size[ch[r][1]];
add[r] = 0;
}
}
void PushUp(int r)
{
size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;
sum[r] = sum[ch[r][0]] + sum[ch[r][1]] + key[r] + add[r];
}
void Rotate(int x,int kind)
{
int y = pre[x];
PushDown(y);
PushDown(x);
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
PushUp(y);
}
void Splay(int r,int goal)
{
while(pre[r] != goal)
{
int y = pre[r],z = pre[y];
PushDown(z); PushDown(y); PushDown(r);
if(pre[pre[r]] == goal)
{
Rotate(r,ch[pre[r]][0]==r);
}
else
{
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r)
{
Rotate(r,!kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
PushUp(r);
if(goal == 0) root = r;
}
void RotateTo(int k,int goal)
{
int r = root;
PushDown(r);
while(size[ch[r][0]] != k)
{
if(k < size[ch[r][0]])
r = ch[r][0];
else
{
k -= (size[ch[r][0]] + 1);
r = ch[r][1];
}
PushDown(r);
}
Splay(r,goal);
}
void Update(int l,int r)
{
int k;
scanf("%d",&k);
RotateTo(l-1,0);
RotateTo(r+1,root);
add[Key_value] += k;
sum[Key_value] += size[Key_value]*k;
}
LL Query(int l,int r)
{
RotateTo(l-1,0);
RotateTo(r+1,root);
return sum[Key_value];
}
void solve(int n,int q)
{
for(int i = 0;i < n;i++)
{
scanf("%d",&a[i]);
}
init(n);
while(q--)
{
char str[10];
int x,y;
scanf("%s%d%d",str,&x,&y);
if(str[0] == 'Q')
printf("%lld\n",Query(x,y));
else Update(x,y);
}
}
}spt;
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=EOF)
{
spt.solve(n,q);
}
return 0;
}