原本应该是线段树板刷的题目,现在用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; }