原本应该是线段树板刷的题目,现在用splay tree来做一下。就当练练手。
建立初始树的时候按照顺序建立的二叉树。
每个节点存储的信息:
int pre[maxn]; 当前节点的前驱
int ch[maxn][2];当前节点的左右子树
int val[maxn];当前节点的值
int size[maxn];当前节点的子树的节点个数
int add[maxn];当前节点的子树被增加的值
LL sum[maxn];当前节点的子树的总值
当Q X Y的时候,就把x-1节点设置成根节点。y+1节点设置成根节点的右子树。
那么sum[ch[ch[root][1]][0]]即为结果。
当C X Y k的时候,就把x-1节点设置成根节点。y+1节点设置成根节点的右子树。
然后add[ch[ch[root][1]][0]]+=k;
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 110000
#define LL long long
struct splaytree
{
int a[maxn];
int pre[maxn];
int ch[maxn][2];
int val[maxn];
int root,tot,n;
int size[maxn];
int add[maxn];
LL sum[maxn];
void init(){
memset(pre,0,sizeof(pre));
memset(ch,0,sizeof(ch));
memset(size,0,sizeof(size));
memset(add,0,sizeof(add));
memset(sum,0,sizeof(sum));
memset(val,0,sizeof(val));
root=tot=0;
start();
}
void newnode(int &r,int father,int k){
r=++tot;
pre[r]=father;
add[r]=0;
sum[r]=k;
val[r]=k;
ch[r][0]=ch[r][1]=0;
size[r]=1;
}
void push_up(int x){
size[x]=size[ch[x][1]]+size[ch[x][0]]+1;
sum[x]=sum[ch[x][1]]+sum[ch[x][0]]+add[x]+val[x];
}
void push_down(int x){
val[x]+=add[x];
add[ch[x][1]]+=add[x];
add[ch[x][0]]+=add[x];
sum[ch[x][1]]+=(LL)add[x]*size[ch[x][1]];
sum[ch[x][0]]+=(LL)add[x]*size[ch[x][0]];
add[x]=0;
}
void rot(int x,int kind){
int y=pre[x];
push_down(x);
push_down(y);
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;
push_up(y);
}
void splay(int x,int goal){
push_down(x);
while(pre[x]!=goal){
if(pre[pre[x]]==goal)rot(x,ch[pre[x]][0]==x);
else{
int y=pre[x];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x){
rot(x,!kind);
rot(x,kind);
}
else{
rot(y,kind);
rot(x,kind);
}
}
}
push_up(x);
if(goal==0)root=x;
}
void rotto(int x,int goal){
int r=root;
push_down(r);
while(size[ch[r][0]]!=x){
if(x<size[ch[r][0]])r=ch[r][0];
else{
x=x-size[ch[r][0]]-1;
r=ch[r][1];
}
push_down(r);
}
splay(r,goal);
}
void update(int l,int r){
int k;
scanf("%d",&k);
rotto(l-1,0);
rotto(r+1,root);
add[ch[ch[root][1]][0]]+=k;
sum[ch[ch[root][1]][0]]+=size[ch[ch[root][1]][0]]*k;
}
LL query(int l,int r){
rotto(l-1,0);
rotto(r+1,root);
return sum[ch[ch[root][1]][0]];
}
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);
push_up(x);
}
void start(){
for(int i=0;i<n;i++)scanf("%d",&a[i]);
newnode(root,0,-1);
newnode(ch[root][1],root,-1);
size[root]=2;
buildtree(ch[ch[root][1]][0],0,n-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
}T;
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q))
{
T.n=n;
T.init();
while(q--){
char str[10];
int x,y;
scanf("%s%d%d",str,&x,&y);
if(str[0]=='Q')
printf("%lld\n",T.query(x,y));
else
T.update(x,y);
}
}
return 0;
}