经典问题,对序列进行区间求和和单点更新操作。可用树状数组或线段树或Splay实现。
我这里使用了Splay。
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <map>
#include <cmath>
#include <stack>
#include <algorithm>
#define Value ch[ch[root][1]][0]
using namespace std;
typedef long long LL ;
const int maxn=50005;
int n;
int a[maxn];
struct Splay
{
int tot,root;
int pre[maxn],ch[maxn][2],val[maxn],size[maxn];
int sum[maxn];
void newNode(int &o,int father,int v)
{
o=++tot;
ch[o][0]=ch[o][1]=0;
pre[o]=father;
sum[o]=val[o]=v;
size[o]=1;
}
void push_up(int o)
{
int ls=ch[o][0],rs=ch[o][1];
size[o]=size[ls]+size[rs]+1;
sum[o]=sum[ls]+sum[rs]+val[o];
}
void build(int &o,int father,int l,int r)
{
if(l>r) return ;
int m=l+(r-l)/2;
newNode(o,father,a[m]);
build(ch[o][0],o,l,m-1);
build(ch[o][1],o,m+1,r);
push_up(o);
}
void update(int k,int v)
{
adjust(getKth(root,k),0);
adjust(getKth(root,k+2),root);
val[Value]+=v;
push_up(Value);
push_up(ch[root][1]);
push_up(root);
}
int getKth(int o,int k)
{
int t=size[ch[o][0]]+1;
if(t==k)
return o;
else if(t>k)
return getKth(ch[o][0],k);
else
return getKth(ch[o][1],k-t);
}
void rotate(int x,int kind)
{
int y=pre[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;
push_up(y);
}
void adjust(int x,int g)
{
while(pre[x]!=g)
{
if(pre[pre[x]]==g)
{
rotate(x,ch[pre[x]][0]==x);
}
else
{
int y=pre[x];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x)
{
rotate(x,!kind);
rotate(x,kind);
}
else
{
rotate(y,kind);
rotate(x,kind);
}
}
}
push_up(x);
if(g==0)
root=x;
}
int getSum(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,r+2),root);
return sum[Value];
}
void init()
{
root=tot=0;
newNode(root,0,-1);
newNode(ch[root][1],root,-1);
for(int i=0; i<n; ++i)
scanf("%d",&a[i]);
build(Value,ch[root][1],0,n-1);
push_up(ch[root][1]);
push_up(root);
}
};
Splay tree;
int main()
{
int T,kase=0;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
tree.init();
char str[12];
int x,y;
printf("Case %d:\n",++kase);
while(scanf("%s",str)&&str[0]!='E')
{
scanf("%d%d",&x,&y);
if(str[0]=='Q')
printf("%d\n",tree.getSum(x,y));
else if(str[0]=='A')
tree.update(x,y);
else
tree.update(x,-y);
}
}
return 0;
}